home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus Special 26 / AMIGAplus Sonderheft 26 (2000)(Falke)(DE)(Track 1 of 2)[!].iso / Tools / GFX-Viewer / Animviewer / mpegvideo_datatype / mpegvideo.c < prev    next >
C/C++ Source or Header  |  1999-03-29  |  105KB  |  3,603 lines

  1.  
  2. /*
  3. **
  4. **  $VER: mpegvideo.c 1.11 (30.10.97)
  5. **  mpegvideo.datatype 1.11
  6. **
  7. **  This file contains C code that implements the
  8. **  video decoder model.
  9. **
  10. **  Written 1996/1997 by Roland 'Gizzy' Mainz
  11. **
  12. */
  13.  
  14. #if 0
  15. #define LOOSE_MPEG 1 /* accept malformed mpeg video streams */
  16. #endif
  17.  
  18. /* project includes */
  19. #include "mpegproto.h"
  20. #include "mpegmyassert.h"
  21. #include "mpegdecoders.h"
  22. #include "mpegutil.h"
  23.  
  24.  
  25. /* local prototypes */
  26. static void         ParseSeqHead( struct MPEGVideoInstData *, VidStream * );
  27. static void         ParseGOP( struct MPEGVideoInstData *, VidStream * );
  28. static int          ParsePicture( struct MPEGVideoInstData *, VidStream * , TimeStamp );
  29. static PictImage   *LockRingEntry( struct MPEGVideoInstData *, VidStream *vid_stream );
  30. static void         ParseSlice( struct MPEGVideoInstData *, VidStream * );
  31. static int          ParseMacroBlock( struct MPEGVideoInstData *, VidStream * );
  32. static void         ReconIMBlock( struct MPEGVideoInstData *, VidStream * , int );
  33. static void         ReconPMBlock( struct MPEGVideoInstData *, VidStream * , int , int , int , int );
  34. static void         ReconBMBlock( struct MPEGVideoInstData *, VidStream * , int , int , int , int );
  35. static void         ReconBiMBlock( struct MPEGVideoInstData *, VidStream * , int , int , int , int , int , int );
  36. static void         ProcessSkippedPFrameMBlocks( struct MPEGVideoInstData *, VidStream * );
  37. static void         ProcessSkippedBFrameMBlocks( struct MPEGVideoInstData *, VidStream * );
  38. static void         ReconSkippedBlock( struct MPEGVideoInstData *, UBYTE * , UBYTE * , int , int , int , int , int , int , int , int );
  39. static void         DoPictureDisplay( struct MPEGVideoInstData *, VidStream * );
  40.  
  41. /* Set up array for fast conversion from zig zag order to row/column coordinates. */
  42. static const
  43. UBYTE zigzag[ 64 ][ 2 ] =
  44. {
  45.   0, 0, 1, 0, 0, 1, 0, 2, 1, 1, 2, 0, 3, 0, 2, 1,
  46.   1, 2, 0, 3, 0, 4, 1, 3, 2, 2, 3, 1, 4, 0, 5, 0,
  47.   4, 1, 3, 2, 2, 3, 1, 4, 0, 5, 0, 6, 1, 5, 2, 4,
  48.   3, 3, 4, 2, 5, 1, 6, 0, 7, 0, 6, 1, 5, 2, 4, 3,
  49.   3, 4, 2, 5, 1, 6, 0, 7, 1, 7, 2, 6, 3, 5, 4, 4,
  50.   5, 3, 6, 2, 7, 1, 7, 2, 6, 3, 5, 4, 4, 5, 3, 6,
  51.   2, 7, 3, 7, 4, 6, 5, 5, 6, 4, 7, 3, 7, 4, 6, 5,
  52.   5, 6, 4, 7, 5, 7, 6, 6, 7, 5, 7, 6, 6, 7, 7, 7
  53. };
  54.  
  55.  
  56. /* Array mapping zigzag to array pointer offset. */
  57. const
  58. UBYTE zigzag_direct[ 64 ] =
  59. {
  60.    0,  1,  8, 16,  9,  2,  3, 10, 17, 24, 32, 25, 18, 11,  4,  5,
  61.   12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13,  6,  7, 14, 21, 28,
  62.   35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51,
  63.   58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63
  64. };
  65.  
  66. /* Initialize P and B skip flags. */
  67. #define No_P_Flag (mvid -> No_P_Flag)
  68. #define No_B_Flag (mvid -> No_B_Flag)
  69.  
  70. /*
  71.  * We use a lookup table to make sure values stay in the 0..255 range.
  72.  * Since this is cropping (ie, x = (x < 0)?0:(x>255)?255:x; ), wee call this
  73.  * table the "crop table".
  74.  * MAX_NEG_CROP is the maximum neg/pos value we can handle.
  75.  */
  76. /*
  77. #define MAX_NEG_CROP     (384)
  78. */
  79. #define MAX_NEG_CROP     (384 * 4) /* shoud fix some assertCrop()-hits, see below */
  80. #define NUM_CROP_ENTRIES (256 + (2 * MAX_NEG_CROP))
  81.  
  82. #ifdef NDEBUG
  83. #define assertCrop( x )
  84. #else
  85. #define assertCrop( x )  assert( ((x) >= (-MAX_NEG_CROP)) && ((x) <= (256 + MAX_NEG_CROP)) )
  86. #endif /* !NDEBUG */
  87.  
  88. static UBYTE cropTbl[ NUM_CROP_ENTRIES ];
  89.  
  90.  
  91. /*
  92.  *--------------------------------------------------------------
  93.  *
  94.  * NewVidStream --
  95.  *
  96.  *    Allocates and initializes a VidStream structure. Takes
  97.  *      as parameter requested size for buffer length.
  98.  *
  99.  * Results:
  100.  *    A pointer to the new VidStream structure.
  101.  *
  102.  * Side effects:
  103.  *      None.
  104.  *
  105.  *--------------------------------------------------------------
  106.  */
  107.  
  108.  
  109. VidStream *NewVidStream( struct MPEGVideoInstData *mvid, int streambuflen )
  110. {
  111.     int           i,
  112.                   j;
  113.     VidStream    *new;
  114.     const
  115.     UBYTE         default_intra_matrix[ 64 ] =
  116.     {
  117.        8, 16, 19, 22, 26, 27, 29, 34,
  118.       16, 16, 22, 24, 27, 29, 34, 37,
  119.       19, 22, 26, 27, 29, 34, 34, 38,
  120.       22, 22, 26, 27, 29, 34, 37, 40,
  121.       22, 26, 27, 29, 32, 35, 40, 48,
  122.       26, 27, 29, 32, 35, 40, 48, 58,
  123.       26, 27, 29, 34, 38, 46, 56, 69,
  124.       27, 29, 35, 38, 46, 56, 69, 83
  125.     };
  126.  
  127.     /* Check for legal buffer length. */
  128.     if( streambuflen < 4 )
  129.       return( NULL );
  130.  
  131.     /* Make buffer length multiple of 4. */
  132.     streambuflen = (streambuflen + 3) >> 2;
  133.  
  134.     /* Allocate memory for new structure. */
  135.     new = (VidStream *)mymalloc( mvid, sizeof( VidStream ) );
  136.  
  137.     /* Initialize pointers to extension and user data. */
  138.     new -> group . ext_data       =
  139.       new -> group . user_data    =
  140.       new -> picture . extra_info =
  141.       new -> picture . user_data  =
  142.       new -> picture . ext_data   =
  143.       new -> slice . extra_info   =
  144.       new -> ext_data             =
  145.       new -> user_data            = NULL;
  146.  
  147.     /* Copy default intra matrix. */
  148.     for( i = 0 ; i < 8 ; i++ )
  149.     {
  150.       for( j = 0 ; j < 8 ; j++ )
  151.       {
  152.         new -> intra_quant_matrix[ j ][ i ] = default_intra_matrix[ i * 8 + j ];
  153.       }
  154.     }
  155.  
  156.     /* Initialize crop table. */
  157.     for( i = (-MAX_NEG_CROP); i < NUM_CROP_ENTRIES - MAX_NEG_CROP ; i++ )
  158.     {
  159.       if( i <= 0 )
  160.       {
  161.         cropTbl[ i + MAX_NEG_CROP ] = 0;
  162.       }
  163.       else
  164.       {
  165.         if( i >= 255 )
  166.         {
  167.           cropTbl[ i + MAX_NEG_CROP ] = 255;
  168.         }
  169.         else
  170.         {
  171.           cropTbl[ i + MAX_NEG_CROP ] = i;
  172.         }
  173.       }
  174.     }
  175.  
  176.     /* Initialize non intra quantization matrix. */
  177.     for( i = 0 ; i < 8 ; i++ )
  178.     {
  179.       for( j = 0 ; j < 8 ; j++ )
  180.       {
  181.         new -> non_intra_quant_matrix[ j ][ i ] = 16;
  182.       }
  183.     }
  184.  
  185.     /* Initialize pointers to image spaces. */
  186.     new -> current = new -> past = new -> future = NULL;
  187.  
  188.     for( i = 0 ; i < RING_BUF_SIZE ; i++ )
  189.     {
  190.       new -> ring[ i ] = NULL;
  191.     }
  192.  
  193.     /* Create buffer. */
  194.     new -> buf_start = (unsigned int *)mymalloc( mvid, ((streambuflen + 1) * 4) );
  195.  
  196.     /* Set max_buf_length to one less than actual length to deal with messy
  197.      * data without proper seq. end codes.
  198.      */
  199.     new -> max_buf_length = streambuflen - 1;
  200.  
  201.     /* Initialize bitstream i/o fields. */
  202.     new -> bit_offset = 0;
  203.     new -> buf_length = 0;
  204.     new -> buffer     = new -> buf_start;
  205.  
  206.     /* Return structure. */
  207.     return( new );
  208. }
  209.  
  210.  
  211. void ResetVidStream( struct MPEGVideoInstData *mvid, VidStream *vid )
  212. {
  213.     int i;
  214.  
  215.     /* Initialize pointers to image spaces. */
  216.     vid -> current = vid -> past = vid -> future = NULL;
  217.  
  218.     /* Initialize rings */
  219.     for( i = 0 ; i < RING_BUF_SIZE ; i++ )
  220.     {
  221.       if( vid -> ring[ i ] )
  222.       {
  223.         vid -> ring[ i ] -> locked = 0;  /* Unlock */
  224.       }
  225.     }
  226.  
  227.     /* Initialize bitstream i/o fields. */
  228.     vid -> bit_offset = 0;
  229.     vid -> buf_length = 0;
  230.     vid -> buffer     = vid -> buf_start;
  231. }
  232.  
  233.  
  234. /*
  235.  *--------------------------------------------------------------
  236.  *
  237.  * NewPictImage --
  238.  *
  239.  *    Allocates and initializes a PictImage structure.
  240.  *      The width and height of the image space are passed in
  241.  *      as parameters.
  242.  *
  243.  * Results:
  244.  *    A pointer to the new PictImage structure.
  245.  *
  246.  * Side effects:
  247.  *    None.
  248.  *
  249.  *--------------------------------------------------------------
  250.  */
  251.  
  252.  
  253. PictImage *NewPictImage( struct MPEGVideoInstData *mvid, unsigned int width, unsigned int height )
  254. {
  255.     PictImage *new;
  256.     ULONG      dispwidth  = MAX( width,  anim_width  );
  257.     ULONG      dispheight = MAX( height, anim_height );
  258.  
  259.     /* Allocate memory space for new structure. */
  260.     new = (PictImage *)mymalloc( mvid, sizeof( PictImage ) );
  261.  
  262.     /* Allocate memory for image spaces. */
  263.     switch( ditherType )
  264.     {
  265.       case FULL_COLOR_DITHER:
  266.       case HAM_DITHER:
  267.           /* Allocate XRGB24 chunky pixel */
  268.           new -> display = (UBYTE *)mymalloc( mvid, (size_t)(dispwidth * dispheight * 4UL) );
  269.           break;
  270.  
  271.       case FULL_COLOR_DITHER16:
  272.           /* Allocate XRGB16 chunky pixel */
  273.           new -> display = (UBYTE *)mymalloc( mvid, (size_t)(dispwidth * dispheight * 2UL) );
  274.           break;
  275.  
  276.       default:
  277.           /* Allocate 8 bit chunky pixel */
  278.           new -> display = (UBYTE *)mymalloc( mvid, (size_t)(dispwidth * dispheight) );
  279.           break;
  280.     }
  281.  
  282.     new -> luminance = (UBYTE *)mymalloc( mvid, (size_t)((width * height)      ) );
  283.     new -> Cr        = (UBYTE *)mymalloc( mvid, (size_t)((width * height) / 4UL) );
  284.     new -> Cb        = (UBYTE *)mymalloc( mvid, (size_t)((width * height) / 4UL) );
  285.  
  286.     /* Reset locked flag. */
  287.     new -> locked = 0;
  288.  
  289.     /* Return pointer to new structure. */
  290.     return( new );
  291. }
  292.  
  293.  
  294. /*
  295.  *--------------------------------------------------------------
  296.  *
  297.  * DestroyPictImage --
  298.  *
  299.  *    Deallocates a PictImage structure.
  300.  *
  301.  * Results:
  302.  *      None.
  303.  *
  304.  * Side effects:
  305.  *    None.
  306.  *
  307.  *--------------------------------------------------------------
  308.  */
  309.  
  310.  
  311. void DestroyPictImage( struct MPEGVideoInstData *mvid, PictImage *apictimage )
  312. {
  313.     if( apictimage -> luminance )
  314.     {
  315.       myfree( mvid, (apictimage -> luminance) );
  316.       apictimage -> luminance = NULL;
  317.     }
  318.  
  319.     if( apictimage -> Cr )
  320.     {
  321.       myfree( mvid, (apictimage -> Cr) );
  322.       apictimage -> Cr = NULL;
  323.     }
  324.  
  325.     if( apictimage -> Cb )
  326.     {
  327.       myfree( mvid, (apictimage -> Cb) );
  328.       apictimage -> Cb = NULL;
  329.     }
  330.  
  331.     if( apictimage -> display )
  332.     {
  333.       myfree( mvid, (apictimage -> display) );
  334.       apictimage -> display = NULL;
  335.     }
  336.  
  337.     myfree( mvid, apictimage );
  338. }
  339.  
  340.  
  341. /*
  342.  *--------------------------------------------------------------
  343.  *
  344.  * mpegVidRsrc --
  345.  *
  346.  *      Parses bit stream until MB_QUANTUM number of
  347.  *      macroblocks have been decoded or current slice or
  348.  *      picture ends, whichever comes first. If the start
  349.  *      of a frame is encountered, the frame is time stamped
  350.  *      with the value passed in time_stamp. If the value
  351.  *      passed in buffer is not null, the video stream buffer
  352.  *      is set to buffer and the length of the buffer is
  353.  *      expected in value passed in through length. The current
  354.  *      video stream is set to vid_stream. If vid_stream
  355.  *      is passed as NULL, a new VidStream structure is created
  356.  *      and initialized and used as the current video stream.
  357.  *
  358.  * Results:
  359.  *      A pointer to the video stream structure used.
  360.  *
  361.  * Side effects:
  362.  *      Bit stream is irreversibly parsed. If a picture is completed,
  363.  *      a function is called to display the frame at the correct time.
  364.  *
  365.  *--------------------------------------------------------------
  366.  */
  367.  
  368.  
  369. VidStream *mpegVidRsrc( struct MPEGVideoInstData *mvid, TimeStamp time_stamp, VidStream *vid_stream )
  370. {
  371.   unsigned int data;
  372.   int          i,
  373.                status;
  374.  
  375.   /* Set global curVidStream to vid_stream. Necessary because bit i/o use
  376.    * curVidStream and are not passed vid_stream. Also set global bitstream
  377.    * parameters.
  378.    */
  379.   curVidStream  =  vid_stream;
  380.   bitOffset     =  curVidStream -> bit_offset;
  381.   curBits       = *curVidStream -> buffer << bitOffset;
  382.   bufLength     =  curVidStream -> buf_length;
  383.   bitBuffer     =  (ULONG *)curVidStream -> buffer;
  384.  
  385.   /* If called for the first time, find start code, make sure it is a sequence start code. */
  386.   if( mvid -> mvid_mpegVidRsrc_first )
  387.   {
  388.     mvid -> mvid_mpegVidRsrc_first = FALSE;
  389.  
  390.     next_start_code( mvid );
  391.     show_bits32( data );
  392.  
  393.     if( data != SEQ_START_CODE )
  394.     {
  395.       error_printf( mvid, "This is not an MPEG stream." );
  396.  
  397.       myexit( mvid, RETURN_FAIL, ERROR_OBJECT_WRONG_TYPE );
  398.     }
  399.   }
  400.  
  401.   /* Get next 32 bits (size of start codes). */
  402.   show_bits32( data );
  403.  
  404.   /* Process according to start code (or parse macroblock if not a start code at all. */
  405.   switch( data )
  406.   {
  407.     case SEQ_END_CODE:
  408.     {
  409.         /* Display last frame. */
  410.         if( vid_stream -> future )
  411.         {
  412.           vid_stream -> current = vid_stream -> future;
  413.           ExecuteDisplay( mvid, vid_stream );
  414.         }
  415.  
  416.         /* Sequence done. Do the right thing. For right now, exit. */
  417. #ifndef NDEBUG
  418.         verbose_printf( mvid, "\nVideo successfully loaded. Done!\n" );
  419. #endif /* !NDEBUG */
  420.  
  421.         myexit( mvid, RETURN_OK, 0L );
  422.     }
  423.         break;
  424.  
  425.     case SEQ_START_CODE:
  426.     {
  427.         /* Sequence start code. Parse sequence header. */
  428.         ParseSeqHead( mvid, vid_stream );
  429.  
  430.         /*
  431.          * Return after sequence start code so that application above can use
  432.          * info in header.
  433.          */
  434.         goto done;
  435.     }
  436.  
  437.     case GOP_START_CODE:
  438.     {
  439.         if( mvid -> mvid_IndexScan )
  440.         {
  441.           mvid -> mvid_Last_PIC_SC_Pos = stream_pos( mvid );
  442.         }
  443.  
  444.         /* Group of Pictures start code. Parse gop header. */
  445.         ParseGOP( mvid, vid_stream );
  446.     }
  447.     case PICTURE_START_CODE:
  448.     {
  449.         /* Be sure that we don't overwrite the last GOP position ! */
  450.         if( (data == PICTURE_START_CODE) && (mvid -> mvid_IndexScan) )
  451.         {
  452.           mvid -> mvid_Last_PIC_SC_Pos = stream_pos( mvid );
  453.         }
  454.  
  455.         /* Picture start code. Parse picture header and first slice header.
  456.          * returns currently only PARSE_OK or SKIP_PICTURE
  457.          */
  458.         status = ParsePicture( mvid, vid_stream, time_stamp );
  459.  
  460.         if( status == SKIP_PICTURE )
  461.         {
  462.           next_start_code( mvid );
  463.  
  464. #ifndef NDEBUG
  465.           verbose_printf( mvid, "Skipping picture..." );
  466. #endif /* !NDEBUG */
  467.  
  468.           while( !next_bits( mvid, 32, PICTURE_START_CODE ) )
  469.           {
  470.             if( next_bits( mvid, 32, GOP_START_CODE ) )
  471.             {
  472.               break;
  473.             }
  474.             else
  475.             {
  476.               if( next_bits( mvid, 32, SEQ_END_CODE ) )
  477.                 break;
  478.             }
  479.  
  480.             flush_bits( 24 );
  481.             next_start_code( mvid );
  482.           }
  483.  
  484. #ifndef NDEBUG
  485.           verbose_printf( mvid, "Done.\n" );
  486. #endif /* !NDEBUG */
  487.  
  488.           /* Add empty frame, but only if we have at least ONE frame (no empty frames before the first frame) */
  489.           if( totNumFrames )
  490.           {
  491.             AddFrame( mvid, NULL, NULL );
  492.           }
  493.  
  494.           goto done;
  495.         }
  496.  
  497.         ParseSlice( mvid, vid_stream );
  498.     }
  499.         break;
  500.  
  501.     default:
  502.     {
  503.         /* Check for slice start code. */
  504.         if( (data >= SLICE_MIN_START_CODE) && (data <= SLICE_MAX_START_CODE) )
  505.         {
  506.           /* Slice start code. Parse slice header. */
  507.           ParseSlice( mvid, vid_stream );
  508.         }
  509.         else
  510.         {
  511.           error_printf( mvid, "other mpeg data sequence code found %lx at %lx\n",
  512.                         data, stream_pos( mvid ) );
  513.  
  514.           goto next_start_code; /* test test (1.10) - try to skip POSSIBLY invalid data */
  515.         }
  516.     }
  517.         break;
  518.   }
  519.  
  520.   /* Parse next MB_QUANTUM macroblocks. */
  521. #if 0
  522.   for( i = 0 ; i < MB_QUANTUM ; i++ )
  523. #else
  524.   i = 0UL;
  525.  
  526.   while( 1 )
  527. #endif
  528.   {
  529.     /* Check to see if actually a startcode and not a macroblock. */
  530.     if( !next_bits( mvid, 23, 0x00000000 ) )
  531.     {
  532.       /* Not start code. Parse Macroblock. */
  533.       if( ParseMacroBlock( mvid, vid_stream ) == SKIP_TO_START_CODE )
  534.       {
  535.         goto next_start_code;
  536.       }
  537.     }
  538.     else
  539.     {
  540.       /* Not macroblock, actually start code. Get start code. */
  541.       next_start_code( mvid );
  542.       show_bits32( data );
  543.  
  544.       /*
  545.        * If start code is outside range of slice start codes, frame is
  546.        * complete, display frame.
  547.        */
  548.  
  549.       if( (data < SLICE_MIN_START_CODE) || (data > SLICE_MAX_START_CODE) )
  550.       {
  551.         DoPictureDisplay( mvid, vid_stream );
  552.       }
  553.  
  554.       break;
  555.     }
  556.  
  557.     if( i > MB_QUANTUM )
  558.     {
  559.       i = 0UL;
  560.       error_printf( mvid, "macroblock quantum overflow %ld\n", (long)MB_QUANTUM );
  561.     }
  562.   }
  563.  
  564.   /* Return pointer to video stream structure. */
  565.   goto done;
  566.  
  567. next_start_code:
  568.   next_start_code( mvid );
  569.  
  570. done:
  571.   /* Copy global bit i/o variables back into vid_stream. */
  572.   vid_stream -> buffer      = (unsigned int *)bitBuffer;
  573.   vid_stream -> buf_length  = bufLength;
  574.   vid_stream -> bit_offset  = bitOffset;
  575.  
  576.   return( vid_stream );
  577. }
  578.  
  579.  
  580. VidStream *mpegVidRsrcScan( struct MPEGVideoInstData *mvid, TimeStamp time_stamp, VidStream *vid_stream )
  581. {
  582.   ULONG data;
  583.   int   status = 0;
  584.  
  585.   /* Set global curVidStream to vid_stream. Necessary because bit i/o use
  586.    * curVidStream and are not passed vid_stream. Also set global bitstream
  587.    * parameters.
  588.    */
  589.   curVidStream  =  vid_stream;
  590.   bitOffset     =  curVidStream -> bit_offset;
  591.   curBits       = *curVidStream -> buffer << bitOffset;
  592.   bufLength     =  curVidStream -> buf_length;
  593.   bitBuffer     =  (ULONG *)curVidStream -> buffer;
  594.  
  595.   /* Get next 32 bits (size of start codes). */
  596.   show_bits32( data );
  597.  
  598.   /* Process according to start code (or parse macroblock if not a start code at all). */
  599.   switch( data )
  600.   {
  601.     case SEQ_END_CODE:
  602.     {
  603.         /* Sequence done. Do the right thing. For right now, exit. */
  604. #ifndef NDEBUG
  605.         verbose_printf( mvid, "\nVideo successfully loaded. Done!\n" );
  606. #endif /* !NDEBUG */
  607.  
  608.         myexit( mvid, RETURN_OK, 0L );
  609.     }
  610.         break;
  611.  
  612.     case SEQ_START_CODE:
  613.     {
  614.         /* Sequence start code. Parse sequence header. */
  615.         ParseSeqHead( mvid, vid_stream );
  616.  
  617.         /*
  618.          * Return after sequence start code so that application above can use
  619.          * info in header.
  620.          */
  621.     }
  622.         break;
  623.  
  624.     case GOP_START_CODE:
  625.     {
  626.         if( mvid -> mvid_IndexScan )
  627.         {
  628.           mvid -> mvid_Last_PIC_SC_Pos = stream_pos( mvid );
  629.         }
  630.  
  631.         /* Group of Pictures start code. Parse gop header. */
  632.         ParseGOP( mvid, vid_stream );
  633.     }
  634.     case PICTURE_START_CODE:
  635.     {
  636.         /* Be sure that we don't overwrite the last GOP position ! */
  637.         if( (data == PICTURE_START_CODE) && (mvid -> mvid_IndexScan) )
  638.         {
  639.           mvid -> mvid_Last_PIC_SC_Pos = stream_pos( mvid );
  640.         }
  641.  
  642.         /* Picture start code. Parse picture header and first slice header.
  643.          * returns currently only PARSE_OK or SKIP_PICTURE
  644.          */
  645.         if( ParsePicture( mvid, vid_stream, time_stamp )
  646. #if 0
  647.  != SKIP_PICTURE
  648. #else
  649. , TRUE
  650. #endif
  651. )
  652.         {
  653.           if( ((vid_stream -> picture . code_type) == I_TYPE) && (mvid -> mvid_IndexScan) )
  654.           {
  655.             mvid -> mvid_LastIFrameNode = NULL;
  656.           }
  657.  
  658.           /* Add empty frame node */
  659.           AddFrame( mvid, (UBYTE *)~0UL, NULL );
  660.  
  661.           if( ((vid_stream -> picture . code_type) == I_TYPE) && (mvid -> mvid_IndexScan) )
  662.           {
  663.             struct FrameNode *lastfn = ((struct FrameNode *)(mvid -> mvid_FrameList . mlh_TailPred));
  664.  
  665.             mvid -> mvid_LastIFrameNode = lastfn;
  666.           }
  667.         }
  668.     }
  669.     default:
  670.     {
  671.         status = SKIP_PICTURE;
  672.     }
  673.         break;
  674.   }
  675.  
  676.   if( status == SKIP_PICTURE )
  677.   {
  678.     next_start_code( mvid );
  679.  
  680.     while( !next_bits( mvid, 32, PICTURE_START_CODE ) )
  681.     {
  682.       if( next_bits( mvid, 32, GOP_START_CODE ) )
  683.       {
  684.         break;
  685.       }
  686.       else
  687.       {
  688.         if( next_bits( mvid, 32, SEQ_END_CODE ) )
  689.           break;
  690.       }
  691.  
  692.       flush_bits( 24 );
  693.       next_start_code( mvid );
  694.     }
  695.   }
  696.  
  697.   /* Copy global bit i/o variables back into vid_stream. */
  698.   vid_stream -> buffer      = (unsigned int *)bitBuffer;
  699.   vid_stream -> buf_length  = bufLength;
  700.   vid_stream -> bit_offset  = bitOffset;
  701.  
  702.   return( vid_stream );
  703. }
  704.  
  705.  
  706. /*
  707.  *--------------------------------------------------------------
  708.  *
  709.  * ParseSeqHead --
  710.  *
  711.  *      Assumes bit stream is at the begining of the sequence
  712.  *      header start code. Parses off the sequence header.
  713.  *
  714.  * Results:
  715.  *      Fills the vid_stream structure with values derived and
  716.  *      decoded from the sequence header. Allocates the pict image
  717.  *      structures based on the dimensions of the image space
  718.  *      found in the sequence header.
  719.  *
  720.  * Side effects:
  721.  *      Bit stream irreversibly parsed off.
  722.  *
  723.  *--------------------------------------------------------------
  724.  */
  725.  
  726.  
  727. static
  728. void ParseSeqHead( struct MPEGVideoInstData *mvid, VidStream *vid_stream )
  729. {
  730.     ULONG data;
  731.     int   i;
  732.  
  733.     /* Flush off sequence start code. */
  734.     flush_bits32;
  735.  
  736.     /* Get horizontal size of image space. */
  737.     get_bits12( data );
  738.     vid_stream -> h_size = data;
  739.  
  740.     /* Get vertical size of image space. */
  741.     get_bits12( data );
  742.     vid_stream -> v_size = data;
  743.  
  744.     /* Calculate macroblock width and height of image space. */
  745.     vid_stream -> mb_width  = (vid_stream -> h_size + 15) / 16;
  746.     vid_stream -> mb_height = (vid_stream -> v_size + 15) / 16;
  747.  
  748.     /* Initialize lmaxx, lmaxy, cmaxx, cmaxy. */
  749.     lmaxx = vid_stream -> mb_width  * 16 - 1;
  750.     lmaxy = vid_stream -> mb_height * 16 - 1;
  751.     cmaxx = vid_stream -> mb_width  *  8 - 1;
  752.     cmaxy = vid_stream -> mb_height *  8 - 1;
  753.  
  754.     /* Initialize ring buffer of pict images now that dimensions of image space are known. */
  755.     if( vid_stream -> ring[ 0 ] == NULL )
  756.     {
  757.       for( i = 0 ; i < RING_BUF_SIZE ; i++ )
  758.       {
  759.         vid_stream -> ring[ i ] = NewPictImage( mvid, ((vid_stream -> mb_width) * 16), ((vid_stream -> mb_height) * 16) );
  760.       }
  761.     }
  762.  
  763.     /* Parse of aspect ratio code. */
  764.     get_bits4( data );
  765.     vid_stream -> aspect_ratio = (UBYTE)data;
  766.  
  767.     /* Parse off picture rate code. */
  768.     get_bits4( data );
  769.     vid_stream -> picture_rate = (UBYTE)data;
  770.  
  771.     /* Parse off bit rate. */
  772.     get_bits18( data );
  773.     vid_stream -> bit_rate = data;
  774.  
  775.     /* Flush marker bit. */
  776.     check_marker;
  777.  
  778.     /* Parse off vbv buffer size. */
  779.     get_bits10( data );
  780.     vid_stream -> vbv_buffer_size = data;
  781.  
  782.     /* Parse off contrained parameter flag. */
  783.     get_bits1( data );
  784.     vid_stream -> const_param_flag = MAKEBOOL( data ); /* TRUE or FALSE */
  785.  
  786.     /* If intra_quant_matrix_flag set, parse off intra quant matrix values. */
  787.     get_bits1( data );
  788.  
  789.     if( data )
  790.     {
  791.       for( i = 0 ; i < 64 ; i++ )
  792.       {
  793.         get_bits8( data );
  794.  
  795.         vid_stream -> intra_quant_matrix[ zigzag[ i ][ 1 ] ][ zigzag[ i ][ 0 ] ] = (UBYTE)data;
  796.       }
  797.     }
  798.  
  799.     /* If non intra quant matrix flag set, parse off non intra quant matrix values. */
  800.     get_bits1( data );
  801.  
  802.     if( data )
  803.     {
  804.       for( i = 0 ; i < 64 ; i++ )
  805.       {
  806.         get_bits8( data );
  807.  
  808.         vid_stream -> non_intra_quant_matrix[ zigzag[ i ][ 1 ] ][ zigzag[ i ][ 0 ] ] = (UBYTE)data;
  809.       }
  810.     }
  811.  
  812.     /* Go to next start code. */
  813.     next_start_code( mvid );
  814.  
  815.     /*
  816.      * If next start code is extension start code, parse off extension data.
  817.      */
  818.     if( next_bits( mvid, 32, EXT_START_CODE ) )
  819.     {
  820.       flush_bits32;
  821.  
  822.       if( vid_stream -> ext_data )
  823.       {
  824.         myfree( mvid, vid_stream -> ext_data );
  825.         vid_stream -> ext_data = NULL;
  826.       }
  827.  
  828.       vid_stream -> ext_data = get_ext_data( mvid );
  829.     }
  830.  
  831.     /* If next start code is user start code, parse off user data. */
  832.     if( next_bits( mvid, 32, USER_START_CODE ) )
  833.     {
  834.       flush_bits32;
  835.  
  836.       if( vid_stream -> user_data )
  837.       {
  838.         myfree( mvid, vid_stream -> user_data );
  839.         vid_stream -> user_data = NULL;
  840.       }
  841.  
  842.       vid_stream -> user_data = get_ext_data( mvid );
  843.     }
  844. }
  845.  
  846.  
  847.  
  848. /*
  849.  *--------------------------------------------------------------
  850.  *
  851.  * ParseGOP --
  852.  *
  853.  *      Parses of group of pictures header from bit stream
  854.  *      associated with vid_stream.
  855.  *
  856.  * Results:
  857.  *      Values in gop header placed into video stream structure.
  858.  *
  859.  * Side effects:
  860.  *      Bit stream irreversibly parsed.
  861.  *
  862.  *--------------------------------------------------------------
  863.  */
  864.  
  865.  
  866. static
  867. void ParseGOP( struct MPEGVideoInstData *mvid, VidStream *vid_stream )
  868. {
  869.     ULONG data;
  870.  
  871.     /* Flush group of pictures start code. WWWWWWOOOOOOOSSSSSSHHHHH!!! */
  872.     flush_bits32;
  873.  
  874.     /* Parse off drop frame flag. */
  875.     get_bits1( data );
  876.     vid_stream -> group . drop_flag = MAKEBOOL( data ); /* TRUE or FALSE */
  877.  
  878.     /* Parse off hour component of time code. */
  879.     get_bits5( data );
  880.     vid_stream -> group . tc_hours = (UBYTE)data;
  881.  
  882.     /* Parse off minute component of time code. */
  883.     get_bits6( data );
  884.     vid_stream -> group . tc_minutes = (UBYTE)data;
  885.  
  886.     /* Flush marker bit. */
  887.     check_marker;
  888.  
  889.     /* Parse off second component of time code. */
  890.     get_bits6( data );
  891.     vid_stream -> group . tc_seconds = (UBYTE)data;
  892.  
  893.     /* Parse off picture count component of time code. */
  894.     get_bits6( data );
  895.     vid_stream -> group . tc_pictures = (UBYTE)data;
  896.  
  897.     /* Parse off closed gop and broken link flags. */
  898.     get_bits2( data );
  899.  
  900.     if( data > 1 )
  901.     {
  902.       vid_stream -> group . closed_gop  = TRUE;
  903.       vid_stream -> group . broken_link = (BOOL)(data > 2);
  904.     }
  905.     else
  906.     {
  907.       vid_stream -> group . closed_gop  = FALSE;
  908.       vid_stream -> group . broken_link = MAKEBOOL( data );
  909.     }
  910.  
  911.     /* Goto next start code. */
  912.     next_start_code( mvid );
  913.  
  914.     /* If next start code is extension data, parse off extension data. */
  915.     if( next_bits( mvid, 32, EXT_START_CODE ) )
  916.     {
  917.       flush_bits32;
  918.  
  919.       if( vid_stream -> group . ext_data )
  920.       {
  921.         myfree( mvid, vid_stream -> group . ext_data );
  922.         vid_stream -> group . ext_data = NULL;
  923.       }
  924.  
  925.       vid_stream -> group . ext_data = get_ext_data( mvid );
  926.     }
  927.  
  928.     /* If next start code is user data, parse off user data. */
  929.     if( next_bits( mvid, 32, USER_START_CODE ) )
  930.     {
  931.       flush_bits32;
  932.  
  933.       if( vid_stream -> group . user_data )
  934.       {
  935.         myfree( mvid, vid_stream -> group . user_data );
  936.         vid_stream -> group . user_data = NULL;
  937.       }
  938.  
  939.       vid_stream -> group . user_data = get_ext_data( mvid );
  940.     }
  941. }
  942.  
  943.  
  944. /*
  945.  *--------------------------------------------------------------
  946.  *
  947.  * ParsePicture --
  948.  *
  949.  *      Parses picture header. Marks picture to be presented
  950.  *      at particular time given a time stamp.
  951.  *
  952.  * Results:
  953.  *      Values from picture header put into video stream structure.
  954.  *
  955.  * Side effects:
  956.  *      Bit stream irreversibly parsed.
  957.  *
  958.  *--------------------------------------------------------------
  959.  */
  960.  
  961.  
  962. static
  963. int ParsePicture( struct MPEGVideoInstData *mvid, VidStream *vid_stream, TimeStamp time_stamp )
  964. {
  965.     ULONG data;
  966.  
  967.     /* Flush header start code. */
  968.     flush_bits32;
  969.  
  970.     /* Parse off temporal reference. */
  971.     get_bits10( data );
  972.     vid_stream -> picture . temp_ref = data;
  973.  
  974.     /* Parse of picture type. */
  975.     get_bits3( data );
  976.     vid_stream -> picture . code_type = data;
  977.  
  978.     switch( (vid_stream -> picture . code_type) )
  979.     {
  980.       case I_TYPE:
  981.       {
  982.           /* new in V1.10: track the start of the last I frame */
  983.  
  984.           mvid -> mvid_Last_I_TYPE_Pos = mvid -> mvid_Last_PIC_SC_Pos;
  985.  
  986.           debug_printf( mvid, "I_TYPE frame start at %lx\n", (mvid -> mvid_Last_I_TYPE_Pos) );
  987.       }
  988.           break;
  989.  
  990.       case B_TYPE:
  991.       {
  992.           debug_printf( mvid, "B_TYPE  frame found\n" );
  993.  
  994.           if( No_B_Flag  )
  995.           {
  996.             return( SKIP_PICTURE );
  997.           }
  998.  
  999.           if( (vid_stream -> past == NULL) || (vid_stream -> future == NULL) )
  1000.           {
  1001.             debug_printf( mvid, "no past or future picture\n" );
  1002.  
  1003.             return( SKIP_PICTURE );
  1004.           }
  1005.       }
  1006.           break;
  1007.  
  1008.       case P_TYPE:
  1009.       {
  1010.           debug_printf( mvid, "P_TYPE  frame found\n" );
  1011.  
  1012.           if( No_P_Flag )
  1013.           {
  1014.             return( SKIP_PICTURE );
  1015.           }
  1016.  
  1017.           if( vid_stream -> future == NULL )
  1018.           {
  1019.             debug_printf( mvid, "no future picture\n" );
  1020.  
  1021.             return( SKIP_PICTURE );
  1022.           }
  1023.       }
  1024.           break;
  1025.  
  1026.       case D_TYPE:
  1027.       {
  1028.           debug_printf( mvid, "D_TYPE  frame found\n" );
  1029.       }
  1030.           break;
  1031.  
  1032.       default:
  1033.       {
  1034.           debug_printf( mvid, "unknown frame found\n" );
  1035.       }
  1036.           break;
  1037.     }
  1038.  
  1039.     /* Parse off vbv buffer delay value. */
  1040.     get_bits16( data );
  1041.     vid_stream -> picture . vbv_delay = data;
  1042.  
  1043.     /* If P or B type frame... */
  1044.     if( (vid_stream -> picture . code_type == P_TYPE) || (vid_stream -> picture . code_type == B_TYPE) )
  1045.     {
  1046.       /* Parse off forward vector full pixel flag. */
  1047.       get_bits1( data );
  1048.  
  1049.       vid_stream -> picture . full_pel_forw_vector = MAKEBOOL( data ); /* TRUE or FALSE */
  1050.  
  1051.       /* Parse of forw_r_code. */
  1052.       get_bits3( data );
  1053.  
  1054.       /* Decode forw_r_code into forw_r_size and forw_f. */
  1055.       vid_stream -> picture . forw_r_size = data - 1;
  1056.       vid_stream -> picture . forw_f      = (1 << vid_stream -> picture . forw_r_size);
  1057.     }
  1058.  
  1059.     /* If B type frame... */
  1060.     if( vid_stream -> picture . code_type == B_TYPE )
  1061.     {
  1062.       /* Parse off back vector full pixel flag. */
  1063.       get_bits1( data );
  1064.  
  1065.       vid_stream -> picture . full_pel_back_vector = MAKEBOOL( data ); /* TRUE or FALSE */
  1066.  
  1067.       /* Parse off back_r_code. */
  1068.       get_bits3( data );
  1069.  
  1070.       /* Decode back_r_code into back_r_size and back_f. */
  1071.       vid_stream -> picture . back_r_size = data - 1;
  1072.       vid_stream -> picture . back_f      = (1 << vid_stream -> picture . back_r_size);
  1073.     }
  1074.  
  1075.     /* Get extra bit picture info. */
  1076.     if( vid_stream -> picture . extra_info )
  1077.     {
  1078.       myfree( mvid, vid_stream -> picture . extra_info );
  1079.       vid_stream -> picture . extra_info = NULL;
  1080.     }
  1081.  
  1082.     vid_stream -> picture . extra_info = get_extra_bit_info( mvid );
  1083.  
  1084.     /* Goto next start code. */
  1085.     next_start_code( mvid );
  1086.  
  1087.     /* If start code is extension start code, parse off extension data. */
  1088.     if( next_bits( mvid, 32, EXT_START_CODE ) )
  1089.     {
  1090.       flush_bits32;
  1091.  
  1092.       if( vid_stream -> picture . ext_data )
  1093.       {
  1094.         myfree( mvid, vid_stream -> picture . ext_data );
  1095.         vid_stream -> picture . ext_data = NULL;
  1096.       }
  1097.  
  1098.       vid_stream -> picture . ext_data = get_ext_data( mvid );
  1099.     }
  1100.  
  1101.     /* If start code is user start code, parse off user data. */
  1102.     if( next_bits( mvid, 32, USER_START_CODE ) )
  1103.     {
  1104.       flush_bits32;
  1105.  
  1106.       if( vid_stream -> picture . user_data )
  1107.       {
  1108.         myfree( mvid, vid_stream -> picture . user_data );
  1109.         vid_stream -> picture . user_data = NULL;
  1110.       }
  1111.  
  1112.       vid_stream -> picture . user_data = get_ext_data( mvid );
  1113.     }
  1114.  
  1115.     /* Set current pict image structure to the one just found in ring. */
  1116.     vid_stream -> current = LockRingEntry( mvid, vid_stream );
  1117.  
  1118.     /* Set time stamp. */
  1119.     vid_stream -> current -> show_time = time_stamp;
  1120.  
  1121.     /* Reset past macroblock address field. */
  1122.     vid_stream -> mblock . past_mb_addr = -1;
  1123.  
  1124.     return( PARSE_OK );
  1125. }
  1126.  
  1127.  
  1128. static
  1129. PictImage *LockRingEntry( struct MPEGVideoInstData *mvid, VidStream *vid_stream )
  1130. {
  1131.     /* Find a pict image structure in ring buffer not currently locked. */
  1132.     int i = 0;
  1133.  
  1134.     while( vid_stream -> ring[ i ] -> locked )
  1135.     {
  1136.       if( ++i >= RING_BUF_SIZE )
  1137.       {
  1138.         error_printf( mvid, "Fatal error. Ring buffer full.\n" );
  1139.  
  1140.         myexit( mvid, RETURN_FAIL, ERROR_BUFFER_OVERFLOW );
  1141.       }
  1142.     }
  1143.  
  1144.     return( vid_stream -> ring[ i ] );
  1145. }
  1146.  
  1147.  
  1148. /*
  1149.  *--------------------------------------------------------------
  1150.  *
  1151.  * ParseSlice --
  1152.  *
  1153.  *      Parses off slice header.
  1154.  *
  1155.  * Results:
  1156.  *      Values found in slice header put into video stream structure.
  1157.  *
  1158.  * Side effects:
  1159.  *      Bit stream irreversibly parsed.
  1160.  *
  1161.  *--------------------------------------------------------------
  1162.  */
  1163.  
  1164.  
  1165. static
  1166. void ParseSlice( struct MPEGVideoInstData *mvid, VidStream *vid_stream )
  1167. {
  1168.     ULONG data;
  1169.  
  1170.     /* Flush slice start code. */
  1171.     flush_bits( 24 );
  1172.  
  1173.     /* Parse off slice vertical position. */
  1174.     get_bits8( data );
  1175.     vid_stream -> slice . vert_pos = data;
  1176.  
  1177.     /* Parse off quantization scale. */
  1178.     get_bits5( data );
  1179.     vid_stream -> slice . quant_scale = data;
  1180.  
  1181.     /* Parse off extra bit slice info. */
  1182.     if( vid_stream -> slice . extra_info )
  1183.     {
  1184.       myfree( mvid, vid_stream -> slice . extra_info );
  1185.       vid_stream -> slice . extra_info = NULL;
  1186.     }
  1187.  
  1188.     vid_stream -> slice . extra_info = get_extra_bit_info(mvid);
  1189.  
  1190.     /* Reset past intrablock address. */
  1191.     vid_stream -> mblock . past_intra_addr = -2;
  1192.  
  1193.     /* Reset previous recon motion vectors. */
  1194.     vid_stream -> mblock . recon_right_for_prev  = 0;
  1195.     vid_stream -> mblock . recon_down_for_prev   = 0;
  1196.     vid_stream -> mblock . recon_right_back_prev = 0;
  1197.     vid_stream -> mblock . recon_down_back_prev  = 0;
  1198.  
  1199.     /* Reset macroblock address. */
  1200.     vid_stream -> mblock . mb_address = ((vid_stream -> slice . vert_pos - 1) * vid_stream -> mb_width) - 1;
  1201.  
  1202.     /* Reset past dct dc y, cr, and cb values. */
  1203.     vid_stream -> block . dct_dc_y_past  = 1024;
  1204.     vid_stream -> block . dct_dc_cr_past = 1024;
  1205.     vid_stream -> block . dct_dc_cb_past = 1024;
  1206. }
  1207.  
  1208.  
  1209. /*
  1210.  *--------------------------------------------------------------
  1211.  *
  1212.  * ParseMacroBlock --
  1213.  *
  1214.  *      Parseoff macroblock. Reconstructs DCT values. Applies
  1215.  *      inverse DCT, reconstructs motion vectors, calculates and
  1216.  *      set pixel values for macroblock in current pict image
  1217.  *      structure.
  1218.  *
  1219.  * Results:
  1220.  *      Here's where everything really happens. Welcome to the
  1221.  *      heart of darkness.
  1222.  *
  1223.  * Side effects:
  1224.  *      Bit stream irreversibly parsed off.
  1225.  *
  1226.  *--------------------------------------------------------------
  1227.  */
  1228.  
  1229.  
  1230. static
  1231. int ParseMacroBlock( struct MPEGVideoInstData *mvid, VidStream *vid_stream )
  1232. {
  1233.   int          addr_incr;
  1234.   unsigned int data;
  1235.   int          mask,
  1236.                i,
  1237.                recon_right_for      = 0,
  1238.                recon_down_for       = 0,
  1239.                recon_right_back     = 0,
  1240.                recon_down_back      = 0;
  1241.   int          zero_block_flag      = 0;
  1242.   BOOL         mb_quant         = FALSE,
  1243.                mb_motion_forw   = FALSE,
  1244.                mb_motion_back   = FALSE,
  1245.                mb_pattern       = FALSE;
  1246.  
  1247.   if( vid_stream -> current == NULL )
  1248.   {
  1249.     error_printf( mvid, "ParseMacroBlock: no current frame\n" );
  1250.     myexit( mvid, RETURN_FAIL, ERROR_BUFFER_OVERFLOW );
  1251.   }
  1252.  
  1253.   /* Parse off macroblock address increment and add to macroblock address. */
  1254.   do
  1255.   {
  1256.     DecodeMBAddrInc( addr_incr );
  1257.  
  1258.     if( addr_incr == MB_ESCAPE )
  1259.     {
  1260.       vid_stream -> mblock . mb_address += 33;
  1261.       addr_incr = MB_STUFFING;
  1262.     }
  1263.   } while( addr_incr == MB_STUFFING );
  1264.  
  1265.   vid_stream -> mblock . mb_address += addr_incr;
  1266.  
  1267.   if( (vid_stream -> mblock . mb_address) > ((vid_stream -> mb_height) * (vid_stream -> mb_width) - 1) )
  1268.   {
  1269.     return( SKIP_TO_START_CODE );
  1270.   }
  1271.  
  1272.   /* If macroblocks have been skipped, process skipped macroblocks. */
  1273.   if( ((vid_stream -> mblock . mb_address) - (vid_stream -> mblock . past_mb_addr)) > 1 )
  1274.   {
  1275.     switch( vid_stream -> picture . code_type )
  1276.     {
  1277.       case P_TYPE: ProcessSkippedPFrameMBlocks( mvid, vid_stream );                                                                     break;
  1278.       case B_TYPE: ProcessSkippedBFrameMBlocks( mvid, vid_stream );                                                                     break;
  1279. #ifndef NDEBUG
  1280.       case I_TYPE: break;
  1281.       case D_TYPE: assert( (vid_stream -> picture . code_type) != D_TYPE );                                                       break;
  1282.       default:     error_printf( mvid, "assert %s %ld: unknown macro block %ld\n", __FILE__, __LINE__, (vid_stream -> picture . code_type) ); break;
  1283. #endif /* !NDEBUG */
  1284.     }
  1285.   }
  1286.  
  1287.   /* Set past macroblock address to current macroblock address. */
  1288.   vid_stream -> mblock . past_mb_addr = vid_stream -> mblock . mb_address;
  1289.  
  1290.   /* Based on picture type decode macroblock type. */
  1291.   switch( vid_stream -> picture . code_type )
  1292.   {
  1293.     case I_TYPE: DecodeMBTypeI( mb_quant, mb_motion_forw, mb_motion_back, mb_pattern, (vid_stream -> mblock . mb_intra) );         break;
  1294.     case P_TYPE: DecodeMBTypeP( mb_quant, mb_motion_forw, mb_motion_back, mb_pattern, (vid_stream -> mblock . mb_intra) );         break;
  1295.     case B_TYPE: DecodeMBTypeB( mb_quant, mb_motion_forw, mb_motion_back, mb_pattern, (vid_stream -> mblock . mb_intra) );         break;
  1296. #ifndef NDEBUG
  1297.     case D_TYPE: assert( (vid_stream -> picture . code_type) != D_TYPE );                                                          break;
  1298.     default:     verbose_printf( mvid, "assert %s %ld: unknown macro block %ld\n", __FILE__, __LINE__, (vid_stream -> picture . code_type) );    break;
  1299. #endif /* !NDEBUG */
  1300.   }
  1301.  
  1302.   /* If quantization flag set, parse off new quantization scale. */
  1303.   if( mb_quant )
  1304.   {
  1305.     get_bits5( data );
  1306.     vid_stream -> slice . quant_scale = data;
  1307.   }
  1308.  
  1309.   /* If forward motion vectors exist... */
  1310.   if( mb_motion_forw )
  1311.   {
  1312.     /* Parse off and decode horizontal forward motion vector. */
  1313.     DecodeMotionVectors( vid_stream -> mblock . motion_h_forw_code );
  1314.  
  1315.     /* If horiz. forward r data exists, parse off. */
  1316.     if( ((vid_stream -> picture . forw_f) != 1) && ((vid_stream -> mblock . motion_h_forw_code) != 0) )
  1317.     {
  1318.       get_bitsn( (vid_stream -> picture . forw_r_size), data );
  1319.       vid_stream -> mblock . motion_h_forw_r = data;
  1320.     }
  1321.  
  1322.     /* Parse off and decode vertical forward motion vector. */
  1323.     DecodeMotionVectors( (vid_stream -> mblock . motion_v_forw_code) );
  1324.  
  1325.     /* If vert. forw. r data exists, parse off. */
  1326.     if( ((vid_stream -> picture . forw_f) != 1) && ((vid_stream -> mblock . motion_v_forw_code) != 0) )
  1327.     {
  1328.       get_bitsn( (vid_stream -> picture . forw_r_size), data );
  1329.       vid_stream -> mblock . motion_v_forw_r = data;
  1330.     }
  1331.   }
  1332.  
  1333.   /* If back motion vectors exist... */
  1334.   if( mb_motion_back )
  1335.   {
  1336.     /* Parse off and decode horiz. back motion vector. */
  1337.     DecodeMotionVectors( (vid_stream -> mblock . motion_h_back_code) );
  1338.  
  1339.     /* If horiz. back r data exists, parse off. */
  1340.     if( ((vid_stream -> picture . back_f) != 1) && ((vid_stream -> mblock . motion_h_back_code) != 0) )
  1341.     {
  1342.       get_bitsn( (vid_stream -> picture . back_r_size), data );
  1343.       vid_stream -> mblock . motion_h_back_r = data;
  1344.     }
  1345.  
  1346.     /* Parse off and decode vert. back motion vector. */
  1347.     DecodeMotionVectors( (vid_stream -> mblock . motion_v_back_code) );
  1348.  
  1349.     /* If vert. back r data exists, parse off. */
  1350.     if( ((vid_stream -> picture . back_f) != 1) && ((vid_stream -> mblock . motion_v_back_code) != 0) )
  1351.     {
  1352.       get_bitsn( (vid_stream -> picture . back_r_size), data );
  1353.       vid_stream -> mblock . motion_v_back_r = data;
  1354.     }
  1355.   }
  1356.  
  1357.   /* If mblock pattern flag set, parse and decode CBP (code block pattern). */
  1358.   if( mb_pattern )
  1359.   {
  1360.     DecodeCBP( vid_stream -> mblock . cbp );
  1361.   }
  1362.   else /* Otherwise, set CBP to zero. */
  1363.   {
  1364.     vid_stream -> mblock . cbp = 0;
  1365.   }
  1366.  
  1367.   /* Reconstruct motion vectors depending on picture type. */
  1368.   if( (vid_stream -> picture . code_type) == P_TYPE )
  1369.   {
  1370.     /* If no forw motion vectors, reset previous and current vectors to 0. */
  1371.     if( !mb_motion_forw )
  1372.     {
  1373.       recon_right_for = 0;
  1374.       recon_down_for  = 0;
  1375.       vid_stream -> mblock . recon_right_for_prev = 0;
  1376.       vid_stream -> mblock . recon_down_for_prev  = 0;
  1377.     }
  1378.     /*
  1379.      * Otherwise, compute new forw motion vectors. Reset previous vectors to
  1380.      * current vectors.
  1381.      */
  1382.     else
  1383.     {
  1384.       ComputeForwVector( mvid, (&recon_right_for), (&recon_down_for) );
  1385.     }
  1386.   }
  1387.  
  1388.   if( (vid_stream -> picture . code_type) == B_TYPE )
  1389.   {
  1390.     /* Reset prev. and current vectors to zero if mblock is intracoded. */
  1391.     if( vid_stream -> mblock . mb_intra )
  1392.     {
  1393.       vid_stream -> mblock . recon_right_for_prev   =
  1394.         vid_stream -> mblock . recon_down_for_prev    =
  1395.         vid_stream -> mblock . recon_right_back_prev  =
  1396.         vid_stream -> mblock . recon_down_back_prev   = 0;
  1397.     }
  1398.     else
  1399.     {
  1400.       /* If no forw vectors, current vectors equal prev. vectors. */
  1401.       if( !mb_motion_forw )
  1402.       {
  1403.         recon_right_for = vid_stream -> mblock . recon_right_for_prev;
  1404.         recon_down_for  = vid_stream -> mblock . recon_down_for_prev;
  1405.       }
  1406.       else /* Otherwise compute forw. vectors. Reset prev vectors to new values. */
  1407.       {
  1408.         ComputeForwVector( mvid, &recon_right_for, &recon_down_for );
  1409.       }
  1410.  
  1411.       /* If no back vectors, set back vectors to prev back vectors. */
  1412.       if( !mb_motion_back )
  1413.       {
  1414.         recon_right_back = vid_stream -> mblock . recon_right_back_prev;
  1415.         recon_down_back  = vid_stream -> mblock . recon_down_back_prev;
  1416.       }
  1417.       else /* Otherwise compute new vectors and reset prev. back vectors. */
  1418.       {
  1419.         ComputeBackVector( mvid, &recon_right_back, &recon_down_back );
  1420.       }
  1421.  
  1422.       /*
  1423.        * Store vector existance flags in structure for possible skipped
  1424.        * macroblocks to follow.
  1425.        */
  1426.       vid_stream -> mblock . bpict_past_forw = mb_motion_forw;
  1427.       vid_stream -> mblock . bpict_past_back = mb_motion_back;
  1428.     }
  1429.   }
  1430.  
  1431.   /* For each possible block in macroblock. */
  1432.   if( ditherType == GRAY_DITHER )
  1433.   {
  1434.     for( mask = 32, i = 0 ; i < 4 ; mask >>= 1, i++ )
  1435.     {
  1436.       /* If block exists... */
  1437.       if( (vid_stream -> mblock . mb_intra) || (vid_stream -> mblock . cbp & mask) )
  1438.       {
  1439.         zero_block_flag = 0;
  1440.  
  1441.         ParseReconBlock( mvid, i );
  1442.       }
  1443.       else
  1444.       {
  1445.         zero_block_flag = 1;
  1446.       }
  1447.  
  1448.       /* If macroblock is intra coded... */
  1449.       if( vid_stream -> mblock . mb_intra )
  1450.       {
  1451.         ReconIMBlock( mvid, vid_stream, i );
  1452.       }
  1453.       else
  1454.       {
  1455.         if( mb_motion_forw && mb_motion_back )
  1456.         {
  1457.           ReconBiMBlock( mvid, vid_stream, i, recon_right_for, recon_down_for, recon_right_back, recon_down_back, zero_block_flag );
  1458.         }
  1459.         else
  1460.         {
  1461.           if( mb_motion_forw || (vid_stream -> picture . code_type == P_TYPE) )
  1462.           {
  1463.             ReconPMBlock( mvid, vid_stream, i, recon_right_for, recon_down_for, zero_block_flag );
  1464.           }
  1465.           else
  1466.           {
  1467.             if( mb_motion_back )
  1468.             {
  1469.               ReconBMBlock( mvid, vid_stream, i, recon_right_back, recon_down_back, zero_block_flag );
  1470.             }
  1471.           }
  1472.         }
  1473.       }
  1474.     }
  1475.  
  1476.     /* Kill the Chrominace blocks... */
  1477.     if( (vid_stream -> mblock . mb_intra) || (vid_stream -> mblock . cbp & 0x2) )
  1478.     {
  1479.       ParseAwayBlock( mvid, 4 );
  1480.     }
  1481.  
  1482.     if( (vid_stream -> mblock . mb_intra) || (vid_stream -> mblock . cbp & 0x1) )
  1483.     {
  1484.       ParseAwayBlock( mvid, 5 );
  1485.     }
  1486.   }
  1487.   else
  1488.   {
  1489.     for( mask = 32, i = 0; i < 6; mask >>= 1, i++ )
  1490.     {
  1491.       /* If block exists... */
  1492.       if( (vid_stream -> mblock . mb_intra) || (vid_stream -> mblock . cbp & mask) )
  1493.       {
  1494.         zero_block_flag = 0;
  1495.         ParseReconBlock( mvid, i );
  1496.       }
  1497.       else
  1498.       {
  1499.         zero_block_flag = 1;
  1500.       }
  1501.  
  1502.       /* If macroblock is intra coded... */
  1503.       if( vid_stream -> mblock . mb_intra )
  1504.       {
  1505.         ReconIMBlock( mvid, vid_stream, i );
  1506.       }
  1507.       else
  1508.       {
  1509.         if( mb_motion_forw && mb_motion_back )
  1510.         {
  1511.           ReconBiMBlock( mvid, vid_stream, i, recon_right_for, recon_down_for, recon_right_back, recon_down_back, zero_block_flag);
  1512.         }
  1513.         else
  1514.         {
  1515.           if( mb_motion_forw || (vid_stream -> picture . code_type == P_TYPE) )
  1516.           {
  1517.             ReconPMBlock( mvid, vid_stream, i, recon_right_for, recon_down_for, zero_block_flag );
  1518.           }
  1519.           else
  1520.           {
  1521.             if( mb_motion_back )
  1522.             {
  1523.               ReconBMBlock( mvid, vid_stream, i, recon_right_back, recon_down_back, zero_block_flag );
  1524.             }
  1525.           }
  1526.         }
  1527.       }
  1528.     }
  1529.   }
  1530.  
  1531.   /* If D Type picture, flush marker bit. */
  1532.   if( vid_stream -> picture . code_type == D_TYPE )
  1533.   {
  1534.     check_marker;
  1535.   }
  1536.  
  1537.   /* If macroblock was intracoded, set macroblock past intra address. */
  1538.   if( vid_stream -> mblock . mb_intra )
  1539.   {
  1540.     vid_stream -> mblock . past_intra_addr = vid_stream -> mblock . mb_address;
  1541.   }
  1542.  
  1543.   return( PARSE_OK );
  1544. }
  1545.  
  1546.  
  1547. /*
  1548.  *--------------------------------------------------------------
  1549.  *
  1550.  * ReconIMBlock --
  1551.  *
  1552.  *    Reconstructs intra coded macroblock.
  1553.  *
  1554.  * Results:
  1555.  *    None.
  1556.  *
  1557.  * Side effects:
  1558.  *    None.
  1559.  *
  1560.  *--------------------------------------------------------------
  1561.  */
  1562.  
  1563.  
  1564. static
  1565. void ReconIMBlock( struct MPEGVideoInstData *mvid, VidStream *vid_stream, int bnum )
  1566. {
  1567.   int    mb_row, 
  1568.          mb_col, 
  1569.          row, 
  1570.          col, 
  1571.          row_size, 
  1572.          rr;
  1573.   UBYTE *dest;
  1574.  
  1575.   /* Calculate macroblock row and column from address. */
  1576.   mb_row = (vid_stream -> mblock . mb_address) / (vid_stream -> mb_width);
  1577.   mb_col = (vid_stream -> mblock . mb_address) % (vid_stream -> mb_width);
  1578.  
  1579.   /* If block is luminance block... */
  1580.   if( bnum < 4 )
  1581.   {
  1582.     /* Calculate row and col values for upper left pixel of block. */
  1583.     row = mb_row * 16;
  1584.     col = mb_col * 16;
  1585.  
  1586.     if( bnum > 1 )
  1587.       row += 8;
  1588.  
  1589.     if( bnum % 2 )
  1590.       col += 8;
  1591.  
  1592.     /* Set dest to luminance plane of current pict image. */
  1593.     dest = vid_stream -> current -> luminance;
  1594.  
  1595.     /* Establish row size. */
  1596.     row_size = vid_stream -> mb_width * 16;
  1597.   }
  1598.   else /* Otherwise if block is Cr block... */
  1599.   {
  1600.     if( bnum == 4 )
  1601.     {
  1602.       /* Set dest to Cr plane of current pict image. */
  1603.       dest = vid_stream -> current -> Cr;
  1604.  
  1605.       /* Establish row size. */
  1606.       row_size = vid_stream -> mb_width * 8;
  1607.  
  1608.       /* Calculate row,col for upper left pixel of block. */
  1609.       row = mb_row * 8;
  1610.       col = mb_col * 8;
  1611.     }
  1612.     else /* Otherwise block is Cb block, and ... */
  1613.     {
  1614.       /* Set dest to Cb plane of current pict image. */
  1615.       dest = vid_stream -> current -> Cb;
  1616.  
  1617.       /* Establish row size. */
  1618.       row_size = vid_stream -> mb_width * 8;
  1619.  
  1620.       /* Calculate row,col for upper left pixel value of block. */
  1621.       row = mb_row * 8;
  1622.       col = mb_col * 8;
  1623.     }
  1624.   }
  1625.  
  1626.   /* For each pixel in block, set to cropped reconstructed value from inverse dct. */
  1627.   {
  1628.     WORD  *sp = (&(vid_stream -> block . dct_recon[ 0 ][ 0 ]));
  1629.     UBYTE *cm = cropTbl + MAX_NEG_CROP;
  1630.  
  1631.     dest += row * row_size + col;
  1632.     for( rr = 0 ; rr < 4 ; rr++, sp += 16, dest += row_size )
  1633.     {
  1634.       dest[ 0 ] = cm[ sp[ 0 ] ]; assertCrop( sp[ 0 ] );
  1635.       dest[ 1 ] = cm[ sp[ 1 ] ]; assertCrop( sp[ 1 ] );
  1636.       dest[ 2 ] = cm[ sp[ 2 ] ]; assertCrop( sp[ 2 ] );
  1637.       dest[ 3 ] = cm[ sp[ 3 ] ]; assertCrop( sp[ 3 ] );
  1638.       dest[ 4 ] = cm[ sp[ 4 ] ]; assertCrop( sp[ 4 ] );
  1639.       dest[ 5 ] = cm[ sp[ 5 ] ]; assertCrop( sp[ 5 ] );
  1640.       dest[ 6 ] = cm[ sp[ 6 ] ]; assertCrop( sp[ 6 ] );
  1641.       dest[ 7 ] = cm[ sp[ 7 ] ]; assertCrop( sp[ 7 ] );
  1642.  
  1643.       dest += row_size;
  1644.       dest[ 0 ] = cm[ sp[  8 ] ]; assertCrop( sp[  8 ] );
  1645.       dest[ 1 ] = cm[ sp[  9 ] ]; assertCrop( sp[  9 ] );
  1646.       dest[ 2 ] = cm[ sp[ 10 ] ]; assertCrop( sp[ 10 ] );
  1647.       dest[ 3 ] = cm[ sp[ 11 ] ]; assertCrop( sp[ 11 ] );
  1648.       dest[ 4 ] = cm[ sp[ 12 ] ]; assertCrop( sp[ 12 ] );
  1649.       dest[ 5 ] = cm[ sp[ 13 ] ]; assertCrop( sp[ 13 ] );
  1650.       dest[ 6 ] = cm[ sp[ 14 ] ]; assertCrop( sp[ 14 ] );
  1651.       dest[ 7 ] = cm[ sp[ 15 ] ]; assertCrop( sp[ 15 ] );
  1652.     }
  1653.   }
  1654. }
  1655.  
  1656.  
  1657. /*
  1658.  *--------------------------------------------------------------
  1659.  *
  1660.  * ReconPMBlock --
  1661.  *
  1662.  *    Reconstructs forward predicted macroblocks.
  1663.  *
  1664.  * Results:
  1665.  *      None.
  1666.  *
  1667.  * Side effects:
  1668.  *      None.
  1669.  *
  1670.  *--------------------------------------------------------------
  1671.  */
  1672.  
  1673.  
  1674. static
  1675. void ReconPMBlock( struct MPEGVideoInstData *mvid, VidStream *vid_stream, int bnum, int recon_right_for, int recon_down_for, int zflag )
  1676. {
  1677.   int    mb_row     = 0,
  1678.          mb_col     = 0,
  1679.          row        = 0,
  1680.          col        = 0,
  1681.          row_size   = 0,
  1682.          rr         = 0;
  1683.   UBYTE *dest       = NULL,
  1684.         *past       = NULL;
  1685.   UBYTE *rindex1    = NULL,
  1686.         *rindex2    = NULL;
  1687.   UBYTE *index      = NULL;
  1688.   WORD  *blockvals  = NULL;
  1689.  
  1690. #ifdef LOOSE_MPEG
  1691.   int maxx          = 0,
  1692.       maxy          = 0;
  1693.   int illegalBlock  = 0;
  1694.   int row_start     = 0,
  1695.       row_end       = 0,
  1696.       rfirst        = 0,
  1697.       rlast         = 0,
  1698.       cc            = 0,
  1699.       col_start     = 0,
  1700.       col_end       = 0,
  1701.       cfirst        = 0,
  1702.       clast         = 0;
  1703. #endif /* LOOSE_MPEG */
  1704.  
  1705.   /* Calculate macroblock row and column from address. */
  1706.   mb_row = vid_stream -> mblock.mb_address / vid_stream -> mb_width;
  1707.   mb_col = vid_stream -> mblock.mb_address % vid_stream -> mb_width;
  1708.  
  1709.   if( bnum < 4 )
  1710.   {
  1711.     /* Calculate right_for, down_for motion vectors. */
  1712.     (mvid -> ReconPMBlock_right_for)       = recon_right_for >> 1;
  1713.     (mvid -> ReconPMBlock_down_for)        = recon_down_for >> 1;
  1714.     (mvid -> ReconPMBlock_right_half_for)  = recon_right_for & 0x1;
  1715.     (mvid -> ReconPMBlock_down_half_for)   = recon_down_for & 0x1;
  1716.  
  1717.     /* Set dest to luminance plane of current pict image. */
  1718.     dest = vid_stream -> current -> luminance;
  1719.  
  1720.     if( vid_stream -> picture . code_type == B_TYPE )
  1721.     {
  1722.       if( vid_stream -> past )
  1723.       {
  1724.         past = vid_stream -> past -> luminance;
  1725.       }
  1726.     }
  1727.     else
  1728.     {
  1729.       /* Set predicitive frame to current future frame. */
  1730.       if( vid_stream -> future )
  1731.       {
  1732.         past = vid_stream -> future -> luminance;
  1733.       }
  1734.     }
  1735.  
  1736.     /* Establish row size. */
  1737.     row_size = vid_stream->mb_width << 4;
  1738.  
  1739.     /* Calculate row,col of upper left pixel in block. */
  1740.     row = mb_row << 4;
  1741.     col = mb_col << 4;
  1742.     if (bnum > 1)
  1743.       row += 8;
  1744.     if (bnum % 2)
  1745.       col += 8;
  1746.  
  1747. #ifdef LOOSE_MPEG
  1748.     /* Check for block illegality. */
  1749.     maxx = lmaxx; maxy = lmaxy;
  1750.  
  1751.     if (row + (mvid -> ReconPMBlock_down_for) + 7 > maxy)
  1752.       illegalBlock |= 0x4;
  1753.     else
  1754.       if( row + (mvid -> ReconPMBlock_down_for) < 0 )
  1755.         illegalBlock |= 0x1;
  1756.  
  1757.     if (col + (mvid -> ReconPMBlock_right_for) + 7 > maxx)
  1758.       illegalBlock |= 0x2;
  1759.     else
  1760.       if (col + (mvid -> ReconPMBlock_right_for) < 0)
  1761.         illegalBlock |= 0x8;
  1762.  
  1763. #endif /* LOOSE_MPEG */
  1764.   }
  1765.   else /* Otherwise, block is NOT luminance block, ... */
  1766.   {
  1767.     /* Construct motion vectors. */
  1768.     recon_right_for             /= 2;
  1769.     recon_down_for              /= 2;
  1770.     (mvid -> ReconPMBlock_right_for)       = recon_right_for >> 1;
  1771.     (mvid -> ReconPMBlock_down_for)        = recon_down_for >> 1;
  1772.     (mvid -> ReconPMBlock_right_half_for)  = recon_right_for & 0x1;
  1773.     (mvid -> ReconPMBlock_down_half_for)   = recon_down_for & 0x1;
  1774.  
  1775.     /* Establish row size. */
  1776.     row_size = vid_stream -> mb_width << 3;
  1777.  
  1778.     /* Calculate row,col of upper left pixel in block. */
  1779.     row = mb_row << 3;
  1780.     col = mb_col << 3;
  1781.  
  1782. #ifdef LOOSE_MPEG
  1783.     /* Check for block illegality. */
  1784.     maxx = cmaxx; maxy = cmaxy;
  1785.  
  1786.     if (row + (mvid -> ReconPMBlock_down_for)  + 7 > maxy)
  1787.       illegalBlock |= 0x4;
  1788.     else
  1789.       if (row + (mvid -> ReconPMBlock_down_for) < 0)
  1790.         illegalBlock |= 0x1;
  1791.  
  1792.     if (col + (mvid -> ReconPMBlock_right_for)  + 7 > maxx)
  1793.       illegalBlock  |= 0x2;
  1794.     else
  1795.       if (col + (mvid -> ReconPMBlock_right_for) < 0)
  1796.         illegalBlock |= 0x8;
  1797. #endif /* LOOSE_MPEG */
  1798.  
  1799.     /* If block is Cr block... */
  1800.     if( bnum == 4 )
  1801.     {
  1802.       /* Set dest to Cr plane of current pict image. */
  1803.       dest = vid_stream -> current -> Cr;
  1804.  
  1805.       if( vid_stream -> picture . code_type == B_TYPE )
  1806.       {
  1807.         if( vid_stream -> past )
  1808.         {
  1809.           past = vid_stream -> past -> Cr;
  1810.         }
  1811.       }
  1812.       else
  1813.       {
  1814.         if( vid_stream -> future )
  1815.         {
  1816.           past = vid_stream -> future -> Cr;
  1817.         }
  1818.       }
  1819.     }
  1820.     else /* Otherwise, block is Cb block... */
  1821.     {
  1822.       /* Set dest to Cb plane of current pict image. */
  1823.       dest = vid_stream -> current -> Cb;
  1824.  
  1825.       if( vid_stream -> picture . code_type == B_TYPE )
  1826.       {
  1827.         if( vid_stream -> past )
  1828.         {
  1829.           past = vid_stream -> past -> Cb;
  1830.         }
  1831.       }
  1832.       else
  1833.       {
  1834.         if( vid_stream -> future )
  1835.         {
  1836.           past = vid_stream -> future -> Cb;
  1837.         }
  1838.       }
  1839.     }
  1840.   }
  1841.  
  1842.   /* For each pixel in block... */
  1843. #ifdef LOOSE_MPEG
  1844.   if( illegalBlock )
  1845.   {
  1846.     if( illegalBlock & 0x1 )
  1847.     {
  1848.       row_start = 0;
  1849.       row_end   = row + (mvid -> ReconPMBlock_down_for) + 8;
  1850.       rfirst    = rlast = 8 - row_end;
  1851.     }
  1852.     else
  1853.     {
  1854.       if (illegalBlock & 0x4)
  1855.       {
  1856.         row_start = row + (mvid -> ReconPMBlock_down_for);
  1857.         row_end = maxy+1;
  1858.         rlast = row_end - row_start - 1;
  1859.         rfirst = 0;
  1860.       }
  1861.       else
  1862.       {
  1863.         row_start = row + (mvid -> ReconPMBlock_down_for);
  1864.         row_end = row_start+8;
  1865.         rfirst = 0;
  1866.       }
  1867.     }
  1868.  
  1869.     if( illegalBlock & 0x8 )
  1870.     {
  1871.       col_start = 0;
  1872.       col_end = col + (mvid -> ReconPMBlock_right_for) + 8;
  1873.       cfirst = clast = 8 - col_end;
  1874.     }
  1875.     else
  1876.     {
  1877.       if (illegalBlock & 0x2)
  1878.       {
  1879.         col_start = col + (mvid -> ReconPMBlock_right_for);
  1880.         col_end = maxx + 1;
  1881.         clast = col_end - col_start - 1;
  1882.         cfirst = 0;
  1883.       }
  1884.       else
  1885.       {
  1886.         col_start = col + (mvid -> ReconPMBlock_right_for);
  1887.         col_end = col_start + 8;
  1888.         cfirst = 0;
  1889.       }
  1890.     }
  1891.  
  1892.     for( rr = row_start ; rr < row_end ; rr++ )
  1893.     {
  1894.       rindex1 = past + (rr * row_size) + col_start;
  1895.       index = dest + ((row + rfirst) * row_size) + col + cfirst;
  1896.  
  1897.       for( cc = col_start ; cc < col_end ; cc++ )
  1898.       {
  1899.         *index++ = *rindex1++;
  1900.       }
  1901.     }
  1902.  
  1903.     if (illegalBlock & 0x1)
  1904.     {
  1905.       for (rr = rlast -1; rr >=0; rr--) 
  1906.       {
  1907.         index = dest + ((row + rr) * row_size) + col;
  1908.         rindex1 = dest + ((row + rlast) * row_size) + col;
  1909.         for (cc = 0; cc < 8; cc ++) 
  1910.         {
  1911.           *index++ = *rindex1++;
  1912.         }
  1913.       }
  1914.     }
  1915.     else
  1916.     {
  1917.       if (illegalBlock & 0x4)
  1918.       {
  1919.         for (rr = rlast+1; rr < 8; rr++)
  1920.         {
  1921.           index = dest + ((row + rr) * row_size) + col;
  1922.           rindex1 = dest + ((row + rlast) * row_size) + col;
  1923.           for (cc = 0; cc < 8; cc ++)
  1924.           {
  1925.             *index++ = *rindex1++;
  1926.           }
  1927.         }
  1928.       }
  1929.     }
  1930.  
  1931.     if (illegalBlock & 0x2)
  1932.     {
  1933.       for (cc = clast+1; cc < 8; cc++)
  1934.       {
  1935.         index = dest + (row * row_size) + (col + cc);
  1936.         rindex1 = dest + (row * row_size) + (col + clast);
  1937.         for (rr = 0; rr < 8; rr++)
  1938.         {
  1939.           *index = *rindex1;
  1940.           index += row_size;
  1941.           rindex1 += row_size;
  1942.         }
  1943.       }
  1944.     }
  1945.     else
  1946.     {
  1947.       if (illegalBlock & 0x8)
  1948.       {
  1949.         for (cc = clast-1; cc >= 0; cc--)
  1950.         {
  1951.           index = dest + (row * row_size) + (col + cc);
  1952.           rindex1 = dest + (row * row_size) + (col + clast);
  1953.  
  1954.           for (rr = 0; rr < 8; rr++)
  1955.           {
  1956.             *index = *rindex1;
  1957.             index += row_size;
  1958.             rindex1 += row_size;
  1959.           }
  1960.         }
  1961.       }
  1962.     }
  1963.  
  1964.     if( !zflag )
  1965.     {
  1966.       for( rr = 0 ; rr < 8 ; rr++ )
  1967.       {
  1968.         index = dest + (row * row_size) + col;
  1969.         blockvals = &(vid_stream -> block . dct_recon[ rr ][ 0 ]);
  1970.  
  1971.         index[ 0 ] += blockvals[ 0 ];
  1972.         index[ 1 ] += blockvals[ 1 ];
  1973.         index[ 2 ] += blockvals[ 2 ];
  1974.         index[ 3 ] += blockvals[ 3 ];
  1975.         index[ 4 ] += blockvals[ 4 ];
  1976.         index[ 5 ] += blockvals[ 5 ];
  1977.         index[ 6 ] += blockvals[ 6 ];
  1978.         index[ 7 ] += blockvals[ 7 ];
  1979.       }
  1980.     }
  1981.   }
  1982.   else
  1983.   {
  1984. #endif /* LOOSE_MPEG */
  1985.  
  1986.     index = dest + (row * row_size) + col;
  1987.     rindex1 = past + (row + (mvid -> ReconPMBlock_down_for)) * row_size + col + (mvid -> ReconPMBlock_right_for);
  1988.  
  1989.     blockvals = (&(vid_stream -> block . dct_recon[ 0 ][ 0 ]));
  1990.  
  1991.     /*
  1992.      * Calculate predictive pixel value based on motion vectors and copy to
  1993.      * dest plane.
  1994.      */
  1995.     if( (!(mvid -> ReconPMBlock_down_half_for)) && (!(mvid -> ReconPMBlock_right_half_for)) )
  1996.     {
  1997.       UBYTE *cm = cropTbl + MAX_NEG_CROP;
  1998.  
  1999.       if (!zflag)
  2000.     for (rr = 0; rr < 4; rr++) 
  2001.     {
  2002.       index[ 0 ] = cm[ (int)rindex1[ 0 ] + (int)blockvals[ 0 ] ];
  2003.       index[ 1 ] = cm[ (int)rindex1[ 1 ] + (int)blockvals[ 1 ] ];
  2004.       index[ 2 ] = cm[ (int)rindex1[ 2 ] + (int)blockvals[ 2 ] ];
  2005.       index[ 3 ] = cm[ (int)rindex1[ 3 ] + (int)blockvals[ 3 ] ];
  2006.       index[ 4 ] = cm[ (int)rindex1[ 4 ] + (int)blockvals[ 4 ] ];
  2007.       index[ 5 ] = cm[ (int)rindex1[ 5 ] + (int)blockvals[ 5 ] ];
  2008.       index[ 6 ] = cm[ (int)rindex1[ 6 ] + (int)blockvals[ 6 ] ];
  2009.       index[ 7 ] = cm[ (int)rindex1[ 7 ] + (int)blockvals[ 7 ] ];
  2010.       index += row_size;
  2011.       rindex1 += row_size;
  2012.  
  2013.       index[ 0 ] = cm[ (int)rindex1[ 0 ] + (int)blockvals[  8 ] ];
  2014.       index[ 1 ] = cm[ (int)rindex1[ 1 ] + (int)blockvals[  9 ] ];
  2015.       index[ 2 ] = cm[ (int)rindex1[ 2 ] + (int)blockvals[ 10 ] ];
  2016.       index[ 3 ] = cm[ (int)rindex1[ 3 ] + (int)blockvals[ 11 ] ];
  2017.       index[ 4 ] = cm[ (int)rindex1[ 4 ] + (int)blockvals[ 12 ] ];
  2018.       index[ 5 ] = cm[ (int)rindex1[ 5 ] + (int)blockvals[ 13 ] ];
  2019.       index[ 6 ] = cm[ (int)rindex1[ 6 ] + (int)blockvals[ 14 ] ];
  2020.       index[ 7 ] = cm[ (int)rindex1[ 7 ] + (int)blockvals[ 15 ] ];
  2021.       blockvals += 16;
  2022.       index += row_size;
  2023.       rindex1 += row_size;
  2024.     }
  2025.       else
  2026.       {
  2027.     if ((mvid -> ReconPMBlock_right_for) & 0x1)
  2028.     {
  2029.       /* No alignment, use bye copy */
  2030.       for (rr = 0; rr < 4; rr++)
  2031.       {
  2032.         index[ 0 ] = rindex1[ 0 ];
  2033.         index[ 1 ] = rindex1[ 1 ];
  2034.         index[ 2 ] = rindex1[ 2 ];
  2035.         index[ 3 ] = rindex1[ 3 ];
  2036.         index[ 4 ] = rindex1[ 4 ];
  2037.         index[ 5 ] = rindex1[ 5 ];
  2038.         index[ 6 ] = rindex1[ 6 ];
  2039.         index[ 7 ] = rindex1[ 7 ];
  2040.         index += row_size;
  2041.         rindex1 += row_size;
  2042.  
  2043.         index[ 0 ] = rindex1[ 0 ];
  2044.         index[ 1 ] = rindex1[ 1 ];
  2045.         index[ 2 ] = rindex1[ 2 ];
  2046.         index[ 3 ] = rindex1[ 3 ];
  2047.         index[ 4 ] = rindex1[ 4 ];
  2048.         index[ 5 ] = rindex1[ 5 ];
  2049.         index[ 6 ] = rindex1[ 6 ];
  2050.         index[ 7 ] = rindex1[ 7 ];
  2051.         index += row_size;
  2052.         rindex1 += row_size;
  2053.       }
  2054.     }
  2055.     else
  2056.       if ((mvid -> ReconPMBlock_right_for) & 0x2)
  2057.       {
  2058.       /* Half-word bit aligned, use 16 bit copy */
  2059.       WORD *src = (WORD *)rindex1;
  2060.       WORD *dest = (WORD *)index;
  2061.       row_size >>= 1;
  2062.       for (rr = 0; rr < 4; rr++)
  2063.      {
  2064.         dest[0] = src[0];
  2065.         dest[1] = src[1];
  2066.         dest[2] = src[2];
  2067.         dest[3] = src[3];
  2068.         dest += row_size;
  2069.         src += row_size;
  2070.  
  2071.         dest[0] = src[0];
  2072.         dest[1] = src[1];
  2073.         dest[2] = src[2];
  2074.         dest[3] = src[3];
  2075.         dest += row_size;
  2076.         src += row_size;
  2077.       }
  2078.     }
  2079.     else
  2080.     {
  2081.       /* Word aligned, use 32 bit copy */
  2082.       int *src = (int *)rindex1;
  2083.       int *dest = (int *)index;
  2084.       row_size >>= 2;
  2085.       for (rr = 0; rr < 4; rr++)
  2086.       {
  2087.         dest[0] = src[0];
  2088.         dest[1] = src[1];
  2089.         dest += row_size;
  2090.         src += row_size;
  2091.  
  2092.         dest[0] = src[0];
  2093.         dest[1] = src[1];
  2094.         dest += row_size;
  2095.         src += row_size;
  2096.       }
  2097.     }
  2098.       }
  2099.     }
  2100.     else
  2101.     {
  2102.       UBYTE *cm = cropTbl + MAX_NEG_CROP;
  2103.  
  2104.       rindex2 = rindex1 + (mvid -> ReconPMBlock_right_half_for) + ((mvid -> ReconPMBlock_down_half_for) * row_size);
  2105.       if (!zflag)
  2106.     for (rr = 0; rr < 4; rr++)
  2107.     {
  2108.       index[ 0 ] = cm[ ((int)(rindex1[ 0 ] + rindex2[ 0 ]) >> 1) + blockvals[ 0 ] ];
  2109.       index[ 1 ] = cm[ ((int)(rindex1[ 1 ] + rindex2[ 1 ]) >> 1) + blockvals[ 1 ] ];
  2110.       index[ 2 ] = cm[ ((int)(rindex1[ 2 ] + rindex2[ 2 ]) >> 1) + blockvals[ 2 ] ];
  2111.       index[ 3 ] = cm[ ((int)(rindex1[ 3 ] + rindex2[ 3 ]) >> 1) + blockvals[ 3 ] ];
  2112.       index[ 4 ] = cm[ ((int)(rindex1[ 4 ] + rindex2[ 4 ]) >> 1) + blockvals[ 4 ] ];
  2113.       index[ 5 ] = cm[ ((int)(rindex1[ 5 ] + rindex2[ 5 ]) >> 1) + blockvals[ 5 ] ];
  2114.       index[ 6 ] = cm[ ((int)(rindex1[ 6 ] + rindex2[ 6 ]) >> 1) + blockvals[ 6 ] ];
  2115.       index[ 7 ] = cm[ ((int)(rindex1[ 7 ] + rindex2[ 7 ]) >> 1) + blockvals[ 7 ] ];
  2116.       index += row_size;
  2117.       rindex1 += row_size;
  2118.       rindex2 += row_size;
  2119.  
  2120.       index[ 0 ] = cm[ ((int)(rindex1[ 0 ] + rindex2[ 0 ]) >> 1) + blockvals[  8 ] ];
  2121.       index[ 1 ] = cm[ ((int)(rindex1[ 1 ] + rindex2[ 1 ]) >> 1) + blockvals[  9 ] ];
  2122.       index[ 2 ] = cm[ ((int)(rindex1[ 2 ] + rindex2[ 2 ]) >> 1) + blockvals[ 10 ] ];
  2123.       index[ 3 ] = cm[ ((int)(rindex1[ 3 ] + rindex2[ 3 ]) >> 1) + blockvals[ 11 ] ];
  2124.       index[ 4 ] = cm[ ((int)(rindex1[ 4 ] + rindex2[ 4 ]) >> 1) + blockvals[ 12 ] ];
  2125.       index[ 5 ] = cm[ ((int)(rindex1[ 5 ] + rindex2[ 5 ]) >> 1) + blockvals[ 13 ] ];
  2126.       index[ 6 ] = cm[ ((int)(rindex1[ 6 ] + rindex2[ 6 ]) >> 1) + blockvals[ 14 ] ];
  2127.       index[ 7 ] = cm[ ((int)(rindex1[ 7 ] + rindex2[ 7 ]) >> 1) + blockvals[ 15 ] ];
  2128.       blockvals += 16;
  2129.       index += row_size;
  2130.       rindex1 += row_size;
  2131.       rindex2 += row_size;
  2132.     }
  2133.     else
  2134.     for( rr = 0 ; rr < 4 ; rr++ )
  2135.     {
  2136.       index[ 0 ] = (int)(rindex1[ 0 ] + rindex2[ 0 ]) >> 1;
  2137.       index[ 1 ] = (int)(rindex1[ 1 ] + rindex2[ 1 ]) >> 1;
  2138.       index[ 2 ] = (int)(rindex1[ 2 ] + rindex2[ 2 ]) >> 1;
  2139.       index[ 3 ] = (int)(rindex1[ 3 ] + rindex2[ 3 ]) >> 1;
  2140.       index[ 4 ] = (int)(rindex1[ 4 ] + rindex2[ 4 ]) >> 1;
  2141.       index[ 5 ] = (int)(rindex1[ 5 ] + rindex2[ 5 ]) >> 1;
  2142.       index[ 6 ] = (int)(rindex1[ 6 ] + rindex2[ 6 ]) >> 1;
  2143.       index[ 7 ] = (int)(rindex1[ 7 ] + rindex2[ 7 ]) >> 1;
  2144.       index += row_size;
  2145.       rindex1 += row_size;
  2146.       rindex2 += row_size;
  2147.  
  2148.       index[ 0 ] = (int)(rindex1[ 0 ] + rindex2[ 0 ]) >> 1;
  2149.       index[ 1 ] = (int)(rindex1[ 1 ] + rindex2[ 1 ]) >> 1;
  2150.       index[ 2 ] = (int)(rindex1[ 2 ] + rindex2[ 2 ]) >> 1;
  2151.       index[ 3 ] = (int)(rindex1[ 3 ] + rindex2[ 3 ]) >> 1;
  2152.       index[ 4 ] = (int)(rindex1[ 4 ] + rindex2[ 4 ]) >> 1;
  2153.       index[ 5 ] = (int)(rindex1[ 5 ] + rindex2[ 5 ]) >> 1;
  2154.       index[ 6 ] = (int)(rindex1[ 6 ] + rindex2[ 6 ]) >> 1;
  2155.       index[ 7 ] = (int)(rindex1[ 7 ] + rindex2[ 7 ]) >> 1;
  2156.       index += row_size;
  2157.       rindex1 += row_size;
  2158.       rindex2 += row_size;
  2159.     }
  2160.     }
  2161.  
  2162. #ifdef LOOSE_MPEG
  2163.   }
  2164. #endif /* LOOSE_MPEG */
  2165. }
  2166.  
  2167.  
  2168. /*
  2169.  *--------------------------------------------------------------
  2170.  *
  2171.  * ReconBMBlock --
  2172.  *
  2173.  *    Reconstructs back predicted macroblocks.
  2174.  *
  2175.  * Results:
  2176.  *      None.
  2177.  *
  2178.  * Side effects:
  2179.  *      None.
  2180.  *
  2181.  *--------------------------------------------------------------
  2182.  */
  2183.  
  2184.  
  2185. static
  2186. void ReconBMBlock( struct MPEGVideoInstData *mvid, VidStream *vid_stream, int bnum, int recon_right_back, int recon_down_back, int zflag )
  2187. {
  2188.   int    mb_row          = 0,
  2189.          mb_col          = 0,
  2190.          row, col        = 0,
  2191.          row_size        = 0,
  2192.          rr              = 0;
  2193.   UBYTE *dest            = NULL,
  2194.         *future          = NULL;
  2195.   int    right_back      = 0,
  2196.          down_back       = 0,
  2197.          right_half_back = 0,
  2198.          down_half_back  = 0;
  2199.   UBYTE *rindex1         = NULL,
  2200.         *rindex2         = NULL;
  2201.   UBYTE *index           = NULL;
  2202.   WORD  *blockvals       = NULL;
  2203.  
  2204. #ifdef LOOSE_MPEG
  2205.   int illegalBlock  = 0;
  2206.   int maxx          = 0,
  2207.       maxy          = 0;
  2208.   int row_start     = 0,
  2209.       row_end       = 0,
  2210.       rlast         = 0,
  2211.       rfirst        = 0,
  2212.       cc            = 0,
  2213.       col_start     = 0,
  2214.       col_end       = 0,
  2215.       clast         = 0,
  2216.       cfirst        = 0;
  2217. #endif /* LOOSE_MPEG */
  2218.  
  2219.   /* Calculate macroblock row and column from address. */
  2220.   mb_row = vid_stream -> mblock . mb_address / vid_stream -> mb_width;
  2221.   mb_col = vid_stream -> mblock . mb_address % vid_stream -> mb_width;
  2222.  
  2223.   /* If block is luminance block... */
  2224.   if( bnum < 4 )
  2225.   {
  2226.     /* Calculate right_back, down_bakc motion vectors. */
  2227.     right_back       = recon_right_back >> 1;
  2228.     down_back        = recon_down_back  >> 1;
  2229.     right_half_back  = recon_right_back & 0x1;
  2230.     down_half_back   = recon_down_back  & 0x1;
  2231.  
  2232.     /* Set dest to luminance plane of current pict image. */
  2233.     dest = vid_stream->current->luminance;
  2234.  
  2235.     /*
  2236.      * If future frame exists, set future to luminance plane of future frame.
  2237.      */
  2238.     if (vid_stream->future )
  2239.       future = vid_stream->future->luminance;
  2240.  
  2241.     /* Establish row size. */
  2242.     row_size = vid_stream->mb_width << 4;
  2243.  
  2244.     /* Calculate row,col of upper left pixel in block. */
  2245.     row = mb_row << 4;
  2246.     col = mb_col << 4;
  2247.     if (bnum > 1)
  2248.       row += 8;
  2249.     if (bnum % 2)
  2250.       col += 8;
  2251.  
  2252. #ifdef LOOSE_MPEG
  2253.     /* Check for block illegality. */
  2254.     maxx = lmaxx; maxy = lmaxy;
  2255.  
  2256.     if (row + down_back + 7 > maxy) illegalBlock |= 0x4;
  2257.     else if (row + down_back < 0)  illegalBlock |= 0x1;
  2258.  
  2259.     if (col + right_back + 7 > maxx) illegalBlock |= 0x2;
  2260.     else if (col + right_back < 0) illegalBlock |= 0x8;
  2261. #endif /* LOOSE_MPEG */
  2262.   }
  2263.   else /* Otherwise, block is NOT luminance block, ... */
  2264.   {
  2265.     /* Construct motion vectors. */
  2266.     recon_right_back   /= 2;
  2267.     recon_down_back    /= 2;
  2268.     right_back          = recon_right_back >> 1;
  2269.     down_back           = recon_down_back  >> 1;
  2270.     right_half_back     = recon_right_back & 0x1;
  2271.     down_half_back      = recon_down_back  & 0x1;
  2272.  
  2273.     /* Establish row size. */
  2274.     row_size = vid_stream -> mb_width << 3;
  2275.  
  2276.     /* Calculate row,col of upper left pixel in block. */
  2277.     row = mb_row << 3;
  2278.     col = mb_col << 3;
  2279.  
  2280. #ifdef LOOSE_MPEG
  2281.     /* Check for block illegality. */
  2282.     maxx = cmaxx; maxy = cmaxy;
  2283.  
  2284.     if (row + down_back + 7 > maxy) illegalBlock |= 0x4;
  2285.     else if (row + down_back < 0) illegalBlock |= 0x1;
  2286.  
  2287.     if (col + right_back + 7 > maxx) illegalBlock  |= 0x2;
  2288.     else if (col + right_back < 0) illegalBlock |= 0x8;
  2289. #endif /* LOOSE_MPEG */
  2290.  
  2291.     /* If block is Cr block... */
  2292.     if( bnum == 4 )
  2293.     {
  2294.       /* Set dest to Cr plane of current pict image. */
  2295.       dest = vid_stream -> current -> Cr;
  2296.  
  2297.       /*
  2298.        * If future frame exists, set future to Cr plane of future image.
  2299.        */
  2300.  
  2301.       if( vid_stream -> future )
  2302.         future = vid_stream -> future -> Cr;
  2303.     }
  2304.     else /* Otherwise, block is Cb block... */
  2305.     {
  2306.       /* Set dest to Cb plane of current pict image. */
  2307.       dest = vid_stream -> current -> Cb;
  2308.  
  2309.       /*
  2310.        * If future frame exists, set future to Cb plane of future frame.
  2311.        */
  2312.  
  2313.       if( vid_stream -> future )
  2314.         future = vid_stream -> future -> Cb;
  2315.     }
  2316.   }
  2317.  
  2318.   /* For each pixel in block do... */
  2319. #ifdef LOOSE_MPEG
  2320.   if( illegalBlock )
  2321.   {
  2322.     if( illegalBlock & 0x1 )
  2323.     {
  2324.       row_start = 0;
  2325.       row_end = row+down_back+8;
  2326.       rfirst = rlast = 8 - row_end;
  2327.     }
  2328.     else if (illegalBlock & 0x4)
  2329.     {
  2330.       row_start = row + down_back;
  2331.       row_end = maxy+1;
  2332.       rlast = row_end - row_start - 1;
  2333.       rfirst = 0;
  2334.     }
  2335.     else
  2336.     {
  2337.       row_start = row+down_back;
  2338.       row_end = row_start+8;
  2339.       rfirst = 0;
  2340.     }
  2341.  
  2342.     if (illegalBlock & 0x8)
  2343.     {
  2344.       col_start = 0;
  2345.       col_end = col + right_back + 8;
  2346.       cfirst = clast = 8 - col_end;
  2347.     }
  2348.     else if (illegalBlock & 0x2)
  2349.     {
  2350.       col_start = col + right_back;
  2351.       col_end = maxx + 1;
  2352.       clast = col_end - col_start - 1;
  2353.       cfirst = 0;
  2354.     }
  2355.     else
  2356.     {
  2357.       col_start = col + right_back;
  2358.       col_end = col_start + 8;
  2359.       cfirst = 0;
  2360.     }
  2361.  
  2362.     for (rr = row_start; rr < row_end; rr++)
  2363.     {
  2364.       rindex1 = future + (rr * row_size) + col_start;
  2365.       index = dest + ((row + rfirst) * row_size) + col + cfirst;
  2366.  
  2367.       for (cc = col_start; cc < col_end; cc++)
  2368.       {
  2369.         *index++ = *rindex1++;
  2370.       }
  2371.     }
  2372.  
  2373.     if (illegalBlock & 0x1)
  2374.     {
  2375.       for (rr = rlast -1; rr >=0; rr--)
  2376.       {
  2377.         index = dest + ((row + rr) * row_size) + col;
  2378.         rindex1 = dest + ((row + rlast) * row_size) + col;
  2379.         for (cc = 0; cc < 8; cc ++)
  2380.         {
  2381.           *index++ = *rindex1++;
  2382.         }
  2383.       }
  2384.     }
  2385.     else if (illegalBlock & 0x4)
  2386.     {
  2387.       for (rr = rlast+1; rr < 8; rr++)
  2388.       {
  2389.         index = dest + ((row + rr) * row_size) + col;
  2390.         rindex1 = dest + ((row + rlast) * row_size) + col;
  2391.         for (cc = 0; cc < 8; cc ++)
  2392.         {
  2393.           *index++ = *rindex1++;
  2394.         }
  2395.       }
  2396.     }
  2397.  
  2398.     if (illegalBlock & 0x2) {
  2399.       for (cc = clast+1; cc < 8; cc++) {
  2400.     index = dest + (row * row_size) + (col + cc);
  2401.     rindex1 = dest + (row * row_size) + (col + clast);
  2402.     for (rr = 0; rr < 8; rr++) {
  2403.       *index = *rindex1;
  2404.       index += row_size;
  2405.       rindex1 += row_size;
  2406.     }
  2407.       }
  2408.     }
  2409.     else if (illegalBlock & 0x8) {
  2410.       for (cc = clast-1; cc >= 0; cc--) {
  2411.     index = dest + (row * row_size) + (col + cc);
  2412.     rindex1 = dest + (row * row_size) + (col + clast);
  2413.     for (rr = 0; rr < 8; rr++) {
  2414.       *index = *rindex1;
  2415.       index += row_size;
  2416.       rindex1 += row_size;
  2417.     }
  2418.       }
  2419.     }
  2420.  
  2421.     if (!zflag) {
  2422.       for (rr = 0; rr < 8; rr++) {
  2423.     index = dest + (row*row_size) + col;
  2424.     blockvals = &(vid_stream->block.dct_recon[rr][0]);
  2425.     index[0] += blockvals[0];
  2426.     index[1] += blockvals[1];
  2427.     index[2] += blockvals[2];
  2428.     index[3] += blockvals[3];
  2429.     index[4] += blockvals[4];
  2430.     index[5] += blockvals[5];
  2431.     index[6] += blockvals[6];
  2432.     index[7] += blockvals[7];
  2433.       }
  2434.     }
  2435.   }
  2436.   else {
  2437. #endif /* LOOSE_MPEG */
  2438.  
  2439.     index = dest + (row * row_size) + col;
  2440.     rindex1 = future + (row + down_back) * row_size + col + right_back;
  2441.  
  2442.     blockvals = &(vid_stream->block.dct_recon[0][0]);
  2443.  
  2444.     if ((!right_half_back) && (!down_half_back)) 
  2445.     {
  2446.       UBYTE *cm = cropTbl + MAX_NEG_CROP;
  2447.       if (!zflag)
  2448.     for (rr = 0; rr < 4; rr++) 
  2449.     {
  2450.       index[0] = cm[(int) rindex1[0] + (int) blockvals[0]];
  2451.       index[1] = cm[(int) rindex1[1] + (int) blockvals[1]];
  2452.       index[2] = cm[(int) rindex1[2] + (int) blockvals[2]];
  2453.       index[3] = cm[(int) rindex1[3] + (int) blockvals[3]];
  2454.       index[4] = cm[(int) rindex1[4] + (int) blockvals[4]];
  2455.       index[5] = cm[(int) rindex1[5] + (int) blockvals[5]];
  2456.       index[6] = cm[(int) rindex1[6] + (int) blockvals[6]];
  2457.       index[7] = cm[(int) rindex1[7] + (int) blockvals[7]];
  2458.       index += row_size;
  2459.       rindex1 += row_size;
  2460.  
  2461.       index[0] = cm[(int) rindex1[0] + (int) blockvals[8]];
  2462.       index[1] = cm[(int) rindex1[1] + (int) blockvals[9]];
  2463.       index[2] = cm[(int) rindex1[2] + (int) blockvals[10]];
  2464.       index[3] = cm[(int) rindex1[3] + (int) blockvals[11]];
  2465.       index[4] = cm[(int) rindex1[4] + (int) blockvals[12]];
  2466.       index[5] = cm[(int) rindex1[5] + (int) blockvals[13]];
  2467.       index[6] = cm[(int) rindex1[6] + (int) blockvals[14]];
  2468.       index[7] = cm[(int) rindex1[7] + (int) blockvals[15]];
  2469.       blockvals += 16;
  2470.       index += row_size;
  2471.       rindex1 += row_size;
  2472.     }
  2473.       else {
  2474.     if (right_back & 0x1) {
  2475.       /* No alignment, use bye copy */
  2476.       for (rr = 0; rr < 4; rr++) {
  2477.         index[0] = rindex1[0];
  2478.         index[1] = rindex1[1];
  2479.         index[2] = rindex1[2];
  2480.         index[3] = rindex1[3];
  2481.         index[4] = rindex1[4];
  2482.         index[5] = rindex1[5];
  2483.         index[6] = rindex1[6];
  2484.         index[7] = rindex1[7];
  2485.         index += row_size;
  2486.         rindex1 += row_size;
  2487.  
  2488.         index[0] = rindex1[0];
  2489.         index[1] = rindex1[1];
  2490.         index[2] = rindex1[2];
  2491.         index[3] = rindex1[3];
  2492.         index[4] = rindex1[4];
  2493.         index[5] = rindex1[5];
  2494.         index[6] = rindex1[6];
  2495.         index[7] = rindex1[7];
  2496.         index += row_size;
  2497.         rindex1 += row_size;
  2498.       }
  2499.     } else if (right_back & 0x2) {
  2500.       /* Half-word bit aligned, use 16 bit copy */
  2501.       WORD *src = (WORD *)rindex1;
  2502.       WORD *dest = (WORD *)index;
  2503.       row_size >>= 1;
  2504.       for (rr = 0; rr < 4; rr++) {
  2505.         dest[0] = src[0];
  2506.         dest[1] = src[1];
  2507.         dest[2] = src[2];
  2508.         dest[3] = src[3];
  2509.         dest += row_size;
  2510.         src += row_size;
  2511.  
  2512.         dest[0] = src[0];
  2513.         dest[1] = src[1];
  2514.         dest[2] = src[2];
  2515.         dest[3] = src[3];
  2516.         dest += row_size;
  2517.         src += row_size;
  2518.       }
  2519.     } else {
  2520.       /* Word aligned, use 32 bit copy */
  2521.       int *src = (int *)rindex1;
  2522.       int *dest = (int *)index;
  2523.       row_size >>= 2;
  2524.       for (rr = 0; rr < 4; rr++) {
  2525.         dest[0] = src[0];
  2526.         dest[1] = src[1];
  2527.         dest += row_size;
  2528.         src += row_size;
  2529.  
  2530.         dest[0] = src[0];
  2531.         dest[1] = src[1];
  2532.         dest += row_size;
  2533.         src += row_size;
  2534.       }
  2535.     }
  2536.       }
  2537.     } else {
  2538.       UBYTE *cm = cropTbl + MAX_NEG_CROP;
  2539.       rindex2 = rindex1 + right_half_back + (down_half_back * row_size);
  2540.       if (!zflag)
  2541.     for (rr = 0; rr < 4; rr++) {
  2542.       index[0] = cm[((int) (rindex1[0] + rindex2[0]) >> 1) + blockvals[0]];
  2543.       index[1] = cm[((int) (rindex1[1] + rindex2[1]) >> 1) + blockvals[1]];
  2544.       index[2] = cm[((int) (rindex1[2] + rindex2[2]) >> 1) + blockvals[2]];
  2545.       index[3] = cm[((int) (rindex1[3] + rindex2[3]) >> 1) + blockvals[3]];
  2546.       index[4] = cm[((int) (rindex1[4] + rindex2[4]) >> 1) + blockvals[4]];
  2547.       index[5] = cm[((int) (rindex1[5] + rindex2[5]) >> 1) + blockvals[5]];
  2548.       index[6] = cm[((int) (rindex1[6] + rindex2[6]) >> 1) + blockvals[6]];
  2549.       index[7] = cm[((int) (rindex1[7] + rindex2[7]) >> 1) + blockvals[7]];
  2550.       index += row_size;
  2551.       rindex1 += row_size;
  2552.       rindex2 += row_size;
  2553.  
  2554.       index[0] = cm[((int) (rindex1[0] + rindex2[0]) >> 1) + blockvals[8]];
  2555.       index[1] = cm[((int) (rindex1[1] + rindex2[1]) >> 1) + blockvals[9]];
  2556.       index[2] = cm[((int) (rindex1[2] + rindex2[2]) >> 1) + blockvals[10]];
  2557.       index[3] = cm[((int) (rindex1[3] + rindex2[3]) >> 1) + blockvals[11]];
  2558.       index[4] = cm[((int) (rindex1[4] + rindex2[4]) >> 1) + blockvals[12]];
  2559.       index[5] = cm[((int) (rindex1[5] + rindex2[5]) >> 1) + blockvals[13]];
  2560.       index[6] = cm[((int) (rindex1[6] + rindex2[6]) >> 1) + blockvals[14]];
  2561.       index[7] = cm[((int) (rindex1[7] + rindex2[7]) >> 1) + blockvals[15]];
  2562.       blockvals += 16;
  2563.       index += row_size;
  2564.       rindex1 += row_size;
  2565.       rindex2 += row_size;
  2566.     }
  2567.       else
  2568.     for (rr = 0; rr < 4; rr++) {
  2569.       index[0] = (int) (rindex1[0] + rindex2[0]) >> 1;
  2570.       index[1] = (int) (rindex1[1] + rindex2[1]) >> 1;
  2571.       index[2] = (int) (rindex1[2] + rindex2[2]) >> 1;
  2572.       index[3] = (int) (rindex1[3] + rindex2[3]) >> 1;
  2573.       index[4] = (int) (rindex1[4] + rindex2[4]) >> 1;
  2574.       index[5] = (int) (rindex1[5] + rindex2[5]) >> 1;
  2575.       index[6] = (int) (rindex1[6] + rindex2[6]) >> 1;
  2576.       index[7] = (int) (rindex1[7] + rindex2[7]) >> 1;
  2577.       index += row_size;
  2578.       rindex1 += row_size;
  2579.       rindex2 += row_size;
  2580.  
  2581.       index[0] = (int) (rindex1[0] + rindex2[0]) >> 1;
  2582.       index[1] = (int) (rindex1[1] + rindex2[1]) >> 1;
  2583.       index[2] = (int) (rindex1[2] + rindex2[2]) >> 1;
  2584.       index[3] = (int) (rindex1[3] + rindex2[3]) >> 1;
  2585.       index[4] = (int) (rindex1[4] + rindex2[4]) >> 1;
  2586.       index[5] = (int) (rindex1[5] + rindex2[5]) >> 1;
  2587.       index[6] = (int) (rindex1[6] + rindex2[6]) >> 1;
  2588.       index[7] = (int) (rindex1[7] + rindex2[7]) >> 1;
  2589.       index += row_size;
  2590.       rindex1 += row_size;
  2591.       rindex2 += row_size;
  2592.     }
  2593.     }
  2594.  
  2595. #ifdef LOOSE_MPEG
  2596.   }
  2597. #endif /* LOOSE_MPEG  */
  2598. }
  2599.  
  2600.  
  2601. /*
  2602.  *--------------------------------------------------------------
  2603.  *
  2604.  * ReconBiMBlock --
  2605.  *
  2606.  *    Reconstructs bidirectionally predicted macroblocks.
  2607.  *
  2608.  * Results:
  2609.  *      None.
  2610.  *
  2611.  * Side effects:
  2612.  *      None.
  2613.  *
  2614.  *--------------------------------------------------------------
  2615.  */
  2616.  
  2617.  
  2618. static
  2619. void ReconBiMBlock( struct MPEGVideoInstData *mvid, VidStream *vid_stream, int bnum, int recon_right_for, int recon_down_for, int recon_right_back, int recon_down_back, int zflag )
  2620. {
  2621.   int mb_row, mb_col, row, col, row_size, rr;
  2622.   UBYTE  *dest       = NULL,
  2623.          *past       = NULL,
  2624.          *future     = NULL;
  2625.   int     right_for,
  2626.           down_for
  2627.           /*,right_half_for,*/
  2628.           /*down_half_for*/;
  2629.   int     right_back,
  2630.           down_back
  2631.           /* right_half_back,
  2632.           down_half_back*/;
  2633.   UBYTE  *index      = NULL,
  2634.          *rindex1    = NULL,
  2635.          *bindex1    = NULL;
  2636.   WORD   *blockvals  = NULL;
  2637.   int     forw_row_start,
  2638.           back_row_start,
  2639.           forw_col_start,
  2640.           back_col_start;
  2641.  
  2642. #ifdef LOOSE_MPEG
  2643.   int illegal_forw = 0;
  2644.   int illegal_back = 0;
  2645. #endif /* LOOSE_MPEG */
  2646.  
  2647.   /* Calculate macroblock row and column from address. */
  2648.   mb_row = vid_stream -> mblock . mb_address / vid_stream -> mb_width;
  2649.   mb_col = vid_stream -> mblock . mb_address % vid_stream -> mb_width;
  2650.  
  2651.   /* If block is luminance block... */
  2652.  
  2653.   if( bnum < 4 )
  2654.   {
  2655.     /*
  2656.      * Calculate right_for, down_for, right_half_for, down_half_for,
  2657.      * right_back, down_bakc, right_half_back, and down_half_back, motion
  2658.      * vectors.
  2659.      */
  2660.     right_for = recon_right_for >> 1;
  2661.     down_for = recon_down_for >> 1;
  2662. /*    right_half_for = recon_right_for & 0x1; */
  2663. /*    down_half_for = recon_down_for & 0x1; */
  2664.  
  2665.     right_back = recon_right_back >> 1;
  2666.     down_back = recon_down_back >> 1;
  2667. /*    right_half_back = recon_right_back & 0x1; */
  2668. /*    down_half_back = recon_down_back & 0x1; */
  2669.  
  2670.     /* Set dest to luminance plane of current pict image. */
  2671.  
  2672.     dest = vid_stream -> current -> luminance;
  2673.  
  2674.     /* If past frame exists, set past to luminance plane of past frame. */
  2675.     if( vid_stream -> past )
  2676.       past = vid_stream -> past -> luminance;
  2677.  
  2678.     /* If future frame exists, set future to luminance plane of future frame. */
  2679.     if( vid_stream -> future )
  2680.       future = vid_stream->future->luminance;
  2681.  
  2682.     /* Establish row size. */
  2683.     row_size = (vid_stream->mb_width << 4);
  2684.  
  2685.     /* Calculate row,col of upper left pixel in block. */
  2686.     row = (mb_row << 4);
  2687.     col = (mb_col << 4);
  2688.     if (bnum > 1)
  2689.       row += 8;
  2690.     if (bnum & 0x01)
  2691.       col += 8;
  2692.  
  2693.     forw_col_start = col + right_for;
  2694.     forw_row_start = row + down_for;
  2695.  
  2696.     back_col_start = col + right_back;
  2697.     back_row_start = row + down_back;
  2698.  
  2699. #ifdef LOOSE_MPEG
  2700.     /* Check for illegal pred. blocks. */
  2701.     if (forw_col_start+8 > lmaxx) illegal_forw = 1;
  2702.     else if (forw_col_start < 0) illegal_forw = 1;
  2703.  
  2704.     if (forw_row_start+8 > lmaxy) illegal_forw = 1;
  2705.     else if (forw_row_start < 0) illegal_forw = 1;
  2706.  
  2707.     if (back_col_start+8 > lmaxx) illegal_back = 1;
  2708.     else if (back_col_start < 0) illegal_back = 1;
  2709.  
  2710.     if (back_row_start+8 > lmaxy) illegal_back = 1;
  2711.     else if (back_row_start < 0) illegal_back = 1;
  2712. #endif /* LOOSE_MPEG */
  2713.   }
  2714.   else /* Otherwise, block is NOT luminance block, ... */
  2715.   {
  2716.     /* Construct motion vectors. */
  2717.     recon_right_for /= 2;
  2718.     recon_down_for /= 2;
  2719.     right_for = recon_right_for >> 1;
  2720.     down_for = recon_down_for >> 1;
  2721. /*    right_half_for = recon_right_for & 0x1; */
  2722. /*    down_half_for = recon_down_for & 0x1; */
  2723.  
  2724.     recon_right_back /= 2;
  2725.     recon_down_back /= 2;
  2726.     right_back = recon_right_back >> 1;
  2727.     down_back = recon_down_back >> 1;
  2728. /*    right_half_back = recon_right_back & 0x1; */
  2729. /*    down_half_back = recon_down_back & 0x1; */
  2730.  
  2731.     /* Establish row size. */
  2732.     row_size = (vid_stream->mb_width << 3);
  2733.  
  2734.     /* Calculate row,col of upper left pixel in block. */
  2735.     row = (mb_row << 3);
  2736.     col = (mb_col << 3);
  2737.  
  2738.     forw_col_start = col + right_for;
  2739.     forw_row_start = row + down_for;
  2740.  
  2741.     back_col_start = col + right_back;
  2742.     back_row_start = row + down_back;
  2743.  
  2744. #ifdef LOOSE_MPEG
  2745.     /* Check for illegal pred. blocks. */
  2746.     if (forw_col_start+8 > cmaxx) illegal_forw = 1;
  2747.     else if (forw_col_start < 0) illegal_forw = 1;
  2748.  
  2749.     if (forw_row_start+8 > cmaxy) illegal_forw = 1;
  2750.     else if (forw_row_start < 0) illegal_forw = 1;
  2751.  
  2752.     if (back_col_start+8 > cmaxx) illegal_back = 1;
  2753.     else if (back_col_start < 0) illegal_back = 1;
  2754.  
  2755.     if (back_row_start+8 > cmaxy) illegal_back = 1;
  2756.     else if (back_row_start < 0) illegal_back = 1;
  2757. #endif /* LOOSE_MPEG */
  2758.  
  2759.     /* If block is Cr block... */
  2760.     if( bnum == 4 )
  2761.     {
  2762.       /* Set dest to Cr plane of current pict image. */
  2763.       dest = vid_stream -> current -> Cr;
  2764.  
  2765.       /* If past frame exists, set past to Cr plane of past image. */
  2766.       if( vid_stream -> past )
  2767.         past = vid_stream -> past -> Cr;
  2768.  
  2769.       /* If future frame exists, set future to Cr plane of future image. */
  2770.       if( vid_stream -> future )
  2771.         future = vid_stream -> future -> Cr;
  2772.     }
  2773.     else /* Otherwise, block is Cb block... */
  2774.     {
  2775.       /* Set dest to Cb plane of current pict image. */
  2776.       dest = vid_stream -> current -> Cb;
  2777.  
  2778.       /* If past frame exists, set past to Cb plane of past frame. */
  2779.       if( vid_stream -> past )
  2780.         past = vid_stream -> past -> Cb;
  2781.  
  2782.       /* If future frame exists, set future to Cb plane of future frame. */
  2783.       if( vid_stream -> future )
  2784.         future = vid_stream -> future -> Cb;
  2785.     }
  2786.   }
  2787.  
  2788.   /* For each pixel in block... */
  2789.   index = dest + (row * row_size) + col;
  2790.  
  2791. #ifdef LOOSE_MPEG
  2792.   if (illegal_forw)
  2793.     rindex1 = future + back_row_start * row_size + back_col_start;
  2794.   else
  2795. #endif /* LOOSE_MPEG */
  2796.     rindex1 = past + forw_row_start  * row_size + forw_col_start;
  2797.  
  2798. #ifdef LOOSE_MPEG
  2799.   if (illegal_back)
  2800.     bindex1 = past + forw_row_start * row_size + forw_col_start;
  2801.   else
  2802. #endif /* LOOSE_MPEG */
  2803.     bindex1 = future + back_row_start * row_size + back_col_start;
  2804.  
  2805.   blockvals = (WORD *)(&(vid_stream -> block . dct_recon[ 0 ][ 0 ] ));
  2806.  
  2807.   {
  2808.     UBYTE *cm = cropTbl + MAX_NEG_CROP;
  2809.  
  2810.     if( !zflag )
  2811.     {
  2812.       for( rr = 0 ; rr < 4 ; rr++ )
  2813.       {
  2814.         index[ 0 ] = cm[ ((int)(rindex1[ 0 ] + bindex1[ 0 ]) >> 1) + blockvals[ 0 ] ];
  2815.         index[ 1 ] = cm[ ((int)(rindex1[ 1 ] + bindex1[ 1 ]) >> 1) + blockvals[ 1 ] ];
  2816.         index[ 2 ] = cm[ ((int)(rindex1[ 2 ] + bindex1[ 2 ]) >> 1) + blockvals[ 2 ] ];
  2817.         index[ 3 ] = cm[ ((int)(rindex1[ 3 ] + bindex1[ 3 ]) >> 1) + blockvals[ 3 ] ];
  2818.         index[ 4 ] = cm[ ((int)(rindex1[ 4 ] + bindex1[ 4 ]) >> 1) + blockvals[ 4 ] ];
  2819.         index[ 5 ] = cm[ ((int)(rindex1[ 5 ] + bindex1[ 5 ]) >> 1) + blockvals[ 5 ] ];
  2820.         index[ 6 ] = cm[ ((int)(rindex1[ 6 ] + bindex1[ 6 ]) >> 1) + blockvals[ 6 ] ];
  2821.         index[ 7 ] = cm[ ((int)(rindex1[ 7 ] + bindex1[ 7 ]) >> 1) + blockvals[ 7 ] ];
  2822.         index   += row_size;
  2823.         rindex1 += row_size;
  2824.         bindex1 += row_size;
  2825.  
  2826.         index[ 0 ] = cm[ ((int)(rindex1[ 0 ] + bindex1[ 0 ]) >> 1) + blockvals[  8 ] ];
  2827.         index[ 1 ] = cm[ ((int)(rindex1[ 1 ] + bindex1[ 1 ]) >> 1) + blockvals[  9 ] ];
  2828.         index[ 2 ] = cm[ ((int)(rindex1[ 2 ] + bindex1[ 2 ]) >> 1) + blockvals[ 10 ] ];
  2829.         index[ 3 ] = cm[ ((int)(rindex1[ 3 ] + bindex1[ 3 ]) >> 1) + blockvals[ 11 ] ];
  2830.         index[ 4 ] = cm[ ((int)(rindex1[ 4 ] + bindex1[ 4 ]) >> 1) + blockvals[ 12 ] ];
  2831.         index[ 5 ] = cm[ ((int)(rindex1[ 5 ] + bindex1[ 5 ]) >> 1) + blockvals[ 13 ] ];
  2832.         index[ 6 ] = cm[ ((int)(rindex1[ 6 ] + bindex1[ 6 ]) >> 1) + blockvals[ 14 ] ];
  2833.         index[ 7 ] = cm[ ((int)(rindex1[ 7 ] + bindex1[ 7 ]) >> 1) + blockvals[ 15 ] ];
  2834.         blockvals += 16;
  2835.         index     += row_size;
  2836.         rindex1   += row_size;
  2837.         bindex1   += row_size;
  2838.       }
  2839.     }
  2840.     else
  2841.     {
  2842.       for( rr = 0 ; rr < 4 ; rr++ )
  2843.       {
  2844.         index[ 0 ] = (int)(rindex1[ 0 ] + bindex1[ 0 ]) >> 1;
  2845.         index[ 1 ] = (int)(rindex1[ 1 ] + bindex1[ 1 ]) >> 1;
  2846.         index[ 2 ] = (int)(rindex1[ 2 ] + bindex1[ 2 ]) >> 1;
  2847.         index[ 3 ] = (int)(rindex1[ 3 ] + bindex1[ 3 ]) >> 1;
  2848.         index[ 4 ] = (int)(rindex1[ 4 ] + bindex1[ 4 ]) >> 1;
  2849.         index[ 5 ] = (int)(rindex1[ 5 ] + bindex1[ 5 ]) >> 1;
  2850.         index[ 6 ] = (int)(rindex1[ 6 ] + bindex1[ 6 ]) >> 1;
  2851.         index[ 7 ] = (int)(rindex1[ 7 ] + bindex1[ 7 ]) >> 1;
  2852.         index   += row_size;
  2853.         rindex1 += row_size;
  2854.         bindex1 += row_size;
  2855.  
  2856.         index[ 0 ] = (int)(rindex1[ 0 ] + bindex1[ 0 ]) >> 1;
  2857.         index[ 1 ] = (int)(rindex1[ 1 ] + bindex1[ 1 ]) >> 1;
  2858.         index[ 2 ] = (int)(rindex1[ 2 ] + bindex1[ 2 ]) >> 1;
  2859.         index[ 3 ] = (int)(rindex1[ 3 ] + bindex1[ 3 ]) >> 1;
  2860.         index[ 4 ] = (int)(rindex1[ 4 ] + bindex1[ 4 ]) >> 1;
  2861.         index[ 5 ] = (int)(rindex1[ 5 ] + bindex1[ 5 ]) >> 1;
  2862.         index[ 6 ] = (int)(rindex1[ 6 ] + bindex1[ 6 ]) >> 1;
  2863.         index[ 7 ] = (int)(rindex1[ 7 ] + bindex1[ 7 ]) >> 1;
  2864.         index   += row_size;
  2865.         rindex1 += row_size;
  2866.         bindex1 += row_size;
  2867.       }
  2868.     }
  2869.   }
  2870. }
  2871.  
  2872.  
  2873. /*
  2874.  *--------------------------------------------------------------
  2875.  *
  2876.  * ProcessSkippedPFrameMBlocks --
  2877.  *
  2878.  *    Processes skipped macroblocks in P frames.
  2879.  *
  2880.  * Results:
  2881.  *    Calculates pixel values for luminance, Cr, and Cb planes
  2882.  *      in current pict image for skipped macroblocks.
  2883.  *
  2884.  * Side effects:
  2885.  *    Pixel values in pict image changed.
  2886.  *
  2887.  *--------------------------------------------------------------
  2888.  */
  2889.  
  2890.  
  2891. static
  2892. void ProcessSkippedPFrameMBlocks( struct MPEGVideoInstData *mvid, VidStream *vid_stream )
  2893. {
  2894.   int row_size, half_row, mb_row, mb_col, row, col, rr;
  2895.   int addr, row_incr, half_row_incr, crow, ccol;
  2896.   int *dest, *src, *dest1, *src1;
  2897.  
  2898.   /* Calculate row sizes for luminance and Cr/Cb macroblock areas. */
  2899.   row_size = vid_stream->mb_width << 4;
  2900.   half_row = (row_size >> 1);
  2901.   row_incr = row_size >> 2;
  2902.   half_row_incr = half_row >> 2;
  2903.  
  2904.   /* For each skipped macroblock, do... */
  2905.   for( addr = vid_stream -> mblock . past_mb_addr + 1 ; addr < vid_stream -> mblock . mb_address ; addr++ )
  2906.   {
  2907.     /* Calculate macroblock row and col. */
  2908.     mb_row = addr / vid_stream -> mb_width;
  2909.     mb_col = addr % vid_stream -> mb_width;
  2910.  
  2911.     /* Calculate upper left pixel row,col for luminance plane. */
  2912.     row = mb_row << 4;
  2913.     col = mb_col << 4;
  2914.  
  2915.     /* For each row in macroblock luminance plane... */
  2916.     dest = (int *)(vid_stream -> current -> luminance + (row * row_size) + col);
  2917.     src  = (int *)(vid_stream -> future  -> luminance + (row * row_size) + col);
  2918.  
  2919.     for( rr = 0 ; rr < 8 ; rr++ )
  2920.     {
  2921.       /* Copy pixel values from last I or P picture. */
  2922.       dest[ 0 ] = src[ 0 ];
  2923.       dest[ 1 ] = src[ 1 ];
  2924.       dest[ 2 ] = src[ 2 ];
  2925.       dest[ 3 ] = src[ 3 ];
  2926.       dest += row_incr;
  2927.       src  += row_incr;
  2928.  
  2929.       dest[ 0 ] = src[ 0 ];
  2930.       dest[ 1 ] = src[ 1 ];
  2931.       dest[ 2 ] = src[ 2 ];
  2932.       dest[ 3 ] = src[ 3 ];
  2933.       dest += row_incr;
  2934.       src  += row_incr;
  2935.     }
  2936.  
  2937.     /* Divide row, col to get upper left pixel of macroblock in Cr and Cb planes. */
  2938.     crow = row >> 1;
  2939.     ccol = col >> 1;
  2940.  
  2941.     /* For each row in Cr, and Cb planes... */
  2942.     dest  = (int *)(vid_stream -> current -> Cr + (crow * half_row) + ccol);
  2943.     src   = (int *)(vid_stream -> future  -> Cr + (crow * half_row) + ccol);
  2944.     dest1 = (int *)(vid_stream -> current -> Cb + (crow * half_row) + ccol);
  2945.     src1  = (int *)(vid_stream -> future  -> Cb + (crow * half_row) + ccol);
  2946.  
  2947.     for( rr = 0 ; rr < 4 ; rr++ )
  2948.     {
  2949.       /* Copy pixel values from last I or P picture. */
  2950.       dest[ 0 ] = src[ 0 ];
  2951.       dest[ 1 ] = src[ 1 ];
  2952.  
  2953.       dest1[ 0] = src1[ 0 ];
  2954.       dest1[ 1] = src1[ 1 ];
  2955.  
  2956.       dest  += half_row_incr;
  2957.       src   += half_row_incr;
  2958.       dest1 += half_row_incr;
  2959.       src1  += half_row_incr;
  2960.  
  2961.       dest[ 0 ] = src[ 0 ];
  2962.       dest[ 1 ] = src[ 1 ];
  2963.  
  2964.       dest1[ 0 ] = src1[ 0 ];
  2965.       dest1[ 1 ] = src1[ 1 ];
  2966.  
  2967.       dest  += half_row_incr;
  2968.       src   += half_row_incr;
  2969.       dest1 += half_row_incr;
  2970.       src1  += half_row_incr;
  2971.     }
  2972.   }
  2973.  
  2974.   vid_stream -> mblock . recon_right_for_prev = 0;
  2975.   vid_stream -> mblock . recon_down_for_prev  = 0;
  2976. }
  2977.  
  2978.  
  2979. /*
  2980.  *--------------------------------------------------------------
  2981.  *
  2982.  * ProcessSkippedBFrameMBlocks --
  2983.  *
  2984.  *    Processes skipped macroblocks in B frames.
  2985.  *
  2986.  * Results:
  2987.  *    Calculates pixel values for luminance, Cr, and Cb planes
  2988.  *      in current pict image for skipped macroblocks.
  2989.  *
  2990.  * Side effects:
  2991.  *    Pixel values in pict image changed.
  2992.  *
  2993.  *--------------------------------------------------------------
  2994.  */
  2995.  
  2996.  
  2997. static
  2998. void ProcessSkippedBFrameMBlocks( struct MPEGVideoInstData *mvid, VidStream *vid_stream )
  2999. {
  3000.   int   row_size            = 0,
  3001.         half_row            = 0,
  3002.         mb_row              = 0,
  3003.         mb_col              = 0,
  3004.         row                 = 0,
  3005.         col                 = 0,
  3006.         rr                  = 0;
  3007.   int   right_half_for      = 0,
  3008.         down_half_for       = 0,
  3009.         c_right_half_for    = 0,
  3010.         c_down_half_for     = 0;
  3011.   int   right_half_back     = 0,
  3012.         down_half_back      = 0,
  3013.         c_right_half_back   = 0,
  3014.         c_down_half_back    = 0;
  3015.   int   addr                = 0,
  3016.         right_for           = 0,
  3017.         down_for            = 0;
  3018.   int   recon_right_for     = 0,
  3019.         recon_down_for      = 0;
  3020.   int   recon_right_back    = 0,
  3021.         recon_down_back     = 0;
  3022.   int   right_back          = 0,
  3023.         down_back           = 0;
  3024.   int   c_right_for         = 0,
  3025.         c_down_for          = 0;
  3026.   int   c_right_back        = 0,
  3027.         c_down_back         = 0;
  3028.   UBYTE forw_lum[ 256 ];
  3029.   UBYTE forw_cr[ 64 ],
  3030.         forw_cb[ 64 ];
  3031.   UBYTE back_lum[ 256 ],
  3032.         back_cr[ 64 ],
  3033.         back_cb[ 64 ];
  3034.   int   row_incr            = 0,
  3035.         half_row_incr       = 0;
  3036.   int   ccol                = 0,
  3037.         crow                = 0;
  3038.  
  3039.   /* Calculate row sizes for luminance and Cr/Cb macroblock areas. */
  3040.   row_size      = vid_stream -> mb_width << 4;
  3041.   half_row      = (row_size >> 1);
  3042.   row_incr      = row_size >> 2;
  3043.   half_row_incr = half_row >> 2;
  3044.  
  3045.   /* Establish motion vector codes based on full pixel flag. */
  3046.   if( vid_stream -> picture . full_pel_forw_vector )
  3047.   {
  3048.     recon_right_for = vid_stream -> mblock . recon_right_for_prev << 1;
  3049.     recon_down_for  = vid_stream -> mblock . recon_down_for_prev  << 1;
  3050.   }
  3051.   else
  3052.   {
  3053.     recon_right_for = vid_stream -> mblock . recon_right_for_prev;
  3054.     recon_down_for  = vid_stream -> mblock . recon_down_for_prev;
  3055.   }
  3056.  
  3057.   if( vid_stream -> picture . full_pel_back_vector )
  3058.   {
  3059.     recon_right_back = vid_stream -> mblock . recon_right_back_prev << 1;
  3060.     recon_down_back  = vid_stream -> mblock . recon_down_back_prev  << 1;
  3061.   }
  3062.   else
  3063.   {
  3064.     recon_right_back = vid_stream -> mblock . recon_right_back_prev;
  3065.     recon_down_back  = vid_stream -> mblock . recon_down_back_prev;
  3066.   }
  3067.  
  3068.   /* Calculate motion vectors. */
  3069.   if( vid_stream -> mblock . bpict_past_forw )
  3070.   {
  3071.     right_for       = recon_right_for >> 1;
  3072.     down_for        = recon_down_for >> 1;
  3073.     right_half_for  = recon_right_for & 0x1;
  3074.     down_half_for   = recon_down_for & 0x1;
  3075.  
  3076.     recon_right_for /= 2;
  3077.     recon_down_for  /= 2;
  3078.     c_right_for      = recon_right_for >> 1;
  3079.     c_down_for       = recon_down_for >> 1;
  3080.     c_right_half_for = recon_right_for & 0x1;
  3081.     c_down_half_for  = recon_down_for & 0x1;
  3082.   }
  3083.  
  3084.   if( vid_stream -> mblock . bpict_past_back )
  3085.   {
  3086.     right_back        = recon_right_back >> 1;
  3087.     down_back         = recon_down_back >> 1;
  3088.     right_half_back   = recon_right_back & 0x1;
  3089.     down_half_back    = recon_down_back & 0x1;
  3090.  
  3091.     recon_right_back /= 2;
  3092.     recon_down_back  /= 2;
  3093.     c_right_back      = recon_right_back >> 1;
  3094.     c_down_back       = recon_down_back >> 1;
  3095.     c_right_half_back = recon_right_back & 0x1;
  3096.     c_down_half_back  = recon_down_back & 0x1;
  3097.   }
  3098.  
  3099.   /* For each skipped macroblock, do... */
  3100.   for( addr = vid_stream -> mblock . past_mb_addr + 1; addr < vid_stream -> mblock . mb_address ; addr++ )
  3101.   {
  3102.     /* Calculate macroblock row and col. */
  3103.     mb_row = addr / vid_stream -> mb_width;
  3104.     mb_col = addr % vid_stream -> mb_width;
  3105.  
  3106.     /* Calculate upper left pixel row,col for luminance plane. */
  3107.     row  = mb_row << 4;
  3108.     col  = mb_col << 4;
  3109.     crow = row / 2;
  3110.     ccol = col / 2;
  3111.  
  3112.     /* If forward predicted, calculate prediction values. */
  3113.     if( vid_stream -> mblock . bpict_past_forw )
  3114.     {
  3115.       ReconSkippedBlock( mvid, vid_stream -> past -> luminance, forw_lum, row, col,   row_size, right_for,   down_for,   right_half_for,   down_half_for,   16 );
  3116.       ReconSkippedBlock( mvid, vid_stream -> past -> Cr,        forw_cr,  crow, ccol, half_row, c_right_for, c_down_for, c_right_half_for, c_down_half_for,  8 );
  3117.       ReconSkippedBlock( mvid, vid_stream -> past -> Cb,        forw_cb,  crow, ccol, half_row, c_right_for, c_down_for, c_right_half_for, c_down_half_for,  8 );
  3118.     }
  3119.  
  3120.     /* If back predicted, calculate prediction values. */
  3121.     if( vid_stream -> mblock . bpict_past_back )
  3122.     {
  3123.       ReconSkippedBlock( mvid, vid_stream -> future -> luminance,  back_lum, row,  col,  row_size, right_back,   down_back,   right_half_back,   down_half_back,   16 );
  3124.       ReconSkippedBlock( mvid, vid_stream -> future -> Cr,         back_cr,  crow, ccol, half_row, c_right_back, c_down_back, c_right_half_back, c_down_half_back,  8 );
  3125.       ReconSkippedBlock( mvid, vid_stream -> future -> Cb,         back_cb,  crow, ccol, half_row, c_right_back, c_down_back, c_right_half_back, c_down_half_back,  8 );
  3126.     }
  3127.  
  3128.     if( vid_stream -> mblock . bpict_past_forw && !vid_stream -> mblock . bpict_past_back )
  3129.     {
  3130.       int *dest, *dest1;
  3131.       int *src,  *src1;
  3132.  
  3133.       dest = (int *)(vid_stream -> current -> luminance + (row * row_size) + col);
  3134.       src = (int *)forw_lum;
  3135.  
  3136.       for( rr = 0 ; rr < 16 ; rr++ )
  3137.       {
  3138.         /* memcpy( dest, forw_lum + (rr << 4), 16 );  */
  3139.         dest[ 0 ] = src[ 0 ];
  3140.         dest[ 1 ] = src[ 1 ];
  3141.         dest[ 2 ] = src[ 2 ];
  3142.         dest[ 3 ] = src[ 3 ];
  3143.         dest += row_incr;
  3144.         src  += 4;
  3145.       }
  3146.  
  3147.       dest  = (int *)(vid_stream -> current -> Cr + (crow * half_row) + ccol);
  3148.       dest1 = (int *)(vid_stream -> current -> Cb + (crow * half_row) + ccol);
  3149.       src   = (int *)forw_cr;
  3150.       src1  = (int *)forw_cb;
  3151.  
  3152.       for( rr = 0 ; rr < 8 ; rr++ )
  3153.       {
  3154.         /* memcpy( dest, forw_cr + (rr << 3), 8 ); memcpy( dest1, forw_cb + (rr << 3), 8 ); */
  3155.         dest[ 0 ] = src[ 0 ];
  3156.         dest[ 1 ] = src[ 1 ];
  3157.  
  3158.         dest1[ 0 ] = src1[ 0 ];
  3159.         dest1[ 1 ] = src1[ 1 ];
  3160.  
  3161.         dest  += half_row_incr;
  3162.         dest1 += half_row_incr;
  3163.         src   += 2;
  3164.         src1  += 2;
  3165.       }
  3166.     }
  3167.     else
  3168.       if( vid_stream -> mblock . bpict_past_back && !vid_stream -> mblock . bpict_past_forw )
  3169.       {
  3170.       int *src,  *src1;
  3171.       int *dest, *dest1;
  3172.  
  3173.       dest = (int *)(vid_stream -> current -> luminance + (row * row_size) + col);
  3174.       src = (int *)back_lum;
  3175.  
  3176.       for( rr = 0 ; rr < 16 ; rr++ )
  3177.       {
  3178.         dest[ 0 ] = src[ 0 ];
  3179.         dest[ 1 ] = src[ 1 ];
  3180.         dest[ 2 ] = src[ 2 ];
  3181.         dest[ 3 ] = src[ 3 ];
  3182.  
  3183.         dest += row_incr;
  3184.         src += 4;
  3185.       }
  3186.  
  3187.       dest  = (int *)(vid_stream -> current -> Cr + (crow * half_row) + ccol);
  3188.       dest1 = (int *)(vid_stream -> current -> Cb + (crow * half_row) + ccol);
  3189.       src  = (int *)back_cr;
  3190.       src1 = (int *)back_cb;
  3191.  
  3192.       for( rr = 0 ; rr < 8 ; rr++ )
  3193.       {
  3194.         /* memcpy( dest, back_cr + (rr << 3), 8 ); memcpy( dest1, back_cb + (rr << 3), 8); */
  3195.         dest[ 0 ]  = src[ 0 ];
  3196.         dest[ 1 ]  = src[ 1 ];
  3197.         dest1[ 0 ] = src1[ 0 ];
  3198.         dest1[ 1 ] = src1[ 1 ];
  3199.  
  3200.         dest  += half_row_incr;
  3201.         dest1 += half_row_incr;
  3202.         src   += 2;
  3203.         src1  += 2;
  3204.       }
  3205.     }
  3206.     else
  3207.     {
  3208.       UBYTE *src1, *src2, *src1a, *src2a;
  3209.       UBYTE *dest, *dest1;
  3210.  
  3211.       dest = vid_stream -> current -> luminance + (row * row_size) + col;
  3212.       src1 = forw_lum;
  3213.       src2 = back_lum;
  3214.  
  3215.       for( rr = 0 ; rr < 16 ; rr++ )
  3216.       {
  3217.         dest[  0 ] = (int)(src1[  0 ] + src2[ 0  ]) >> 1;
  3218.         dest[  1 ] = (int)(src1[  1 ] + src2[ 1  ]) >> 1;
  3219.         dest[  2 ] = (int)(src1[  2 ] + src2[ 2  ]) >> 1;
  3220.         dest[  3 ] = (int)(src1[  3 ] + src2[ 3  ]) >> 1;
  3221.         dest[  4 ] = (int)(src1[  4 ] + src2[ 4  ]) >> 1;
  3222.         dest[  5 ] = (int)(src1[  5 ] + src2[ 5  ]) >> 1;
  3223.         dest[  6 ] = (int)(src1[  6 ] + src2[ 6  ]) >> 1;
  3224.         dest[  7 ] = (int)(src1[  7 ] + src2[ 7  ]) >> 1;
  3225.         dest[  8 ] = (int)(src1[  8 ] + src2[ 8  ]) >> 1;
  3226.         dest[  9 ] = (int)(src1[  9 ] + src2[ 9  ]) >> 1;
  3227.         dest[ 10 ] = (int)(src1[ 10 ] + src2[ 10 ]) >> 1;
  3228.         dest[ 11 ] = (int)(src1[ 11 ] + src2[ 11 ]) >> 1;
  3229.         dest[ 12 ] = (int)(src1[ 12 ] + src2[ 12 ]) >> 1;
  3230.         dest[ 13 ] = (int)(src1[ 13 ] + src2[ 13 ]) >> 1;
  3231.         dest[ 14 ] = (int)(src1[ 14 ] + src2[ 14 ]) >> 1;
  3232.         dest[ 15 ] = (int)(src1[ 15 ] + src2[ 15 ]) >> 1;
  3233.  
  3234.         dest += row_size;
  3235.         src1 += 16;
  3236.         src2 += 16;
  3237.       }
  3238.  
  3239.       dest  = vid_stream -> current -> Cr + (crow * half_row) + ccol;
  3240.       dest1 = vid_stream -> current -> Cb + (crow * half_row) + ccol;
  3241.       src1  = forw_cr;
  3242.       src2  = back_cr;
  3243.       src1a = forw_cb;
  3244.       src2a = back_cb;
  3245.  
  3246.       for( rr = 0 ; rr < 8 ; rr++ )
  3247.       {
  3248.         dest[ 0 ] = (int)(src1[ 0 ] + src2[ 0 ]) >> 1;
  3249.         dest[ 1 ] = (int)(src1[ 1 ] + src2[ 1 ]) >> 1;
  3250.         dest[ 2 ] = (int)(src1[ 2 ] + src2[ 2 ]) >> 1;
  3251.         dest[ 3 ] = (int)(src1[ 3 ] + src2[ 3 ]) >> 1;
  3252.         dest[ 4 ] = (int)(src1[ 4 ] + src2[ 4 ]) >> 1;
  3253.         dest[ 5 ] = (int)(src1[ 5 ] + src2[ 5 ]) >> 1;
  3254.         dest[ 6 ] = (int)(src1[ 6 ] + src2[ 6 ]) >> 1;
  3255.         dest[ 7 ] = (int)(src1[ 7 ] + src2[ 7 ]) >> 1;
  3256.  
  3257.         dest += half_row;
  3258.         src1 += 8;
  3259.         src2 += 8;
  3260.  
  3261.         dest1[ 0 ] = (int)(src1a[ 0 ] + src2a[ 0 ]) >> 1;
  3262.         dest1[ 1 ] = (int)(src1a[ 1 ] + src2a[ 1 ]) >> 1;
  3263.         dest1[ 2 ] = (int)(src1a[ 2 ] + src2a[ 2 ]) >> 1;
  3264.         dest1[ 3 ] = (int)(src1a[ 3 ] + src2a[ 3 ]) >> 1;
  3265.         dest1[ 4 ] = (int)(src1a[ 4 ] + src2a[ 4 ]) >> 1;
  3266.         dest1[ 5 ] = (int)(src1a[ 5 ] + src2a[ 5 ]) >> 1;
  3267.         dest1[ 6 ] = (int)(src1a[ 6 ] + src2a[ 6 ]) >> 1;
  3268.         dest1[ 7 ] = (int)(src1a[ 7 ] + src2a[ 7 ]) >> 1;
  3269.  
  3270.         dest1 += half_row;
  3271.         src1a += 8;
  3272.         src2a += 8;
  3273.       }
  3274.     }
  3275.   }
  3276. }
  3277.  
  3278.  
  3279. /*
  3280.  *--------------------------------------------------------------
  3281.  *
  3282.  * ReconSkippedBlock --
  3283.  *
  3284.  *    Reconstructs predictive block for skipped macroblocks
  3285.  *      in B Frames.
  3286.  *
  3287.  * Results:
  3288.  *    No return values.
  3289.  *
  3290.  * Side effects:
  3291.  *    None.
  3292.  *
  3293.  *--------------------------------------------------------------
  3294.  */
  3295.  
  3296.  
  3297. static
  3298. void ReconSkippedBlock( struct MPEGVideoInstData *mvid, UBYTE *source, UBYTE *dest, int row, int col, int row_size, int right, int down, int right_half, int down_half, int width )
  3299. {
  3300.   int    rr;
  3301.   UBYTE *source2;
  3302.  
  3303.   source += ((row + down) * row_size) + col + right;
  3304.  
  3305.   if( width == 16 )
  3306.   {
  3307.     if( (!right_half) && (!down_half) )
  3308.     {
  3309.       if( right & 0x1 )
  3310.       {
  3311.         /* No alignment, use bye copy */
  3312.         for( rr = 0 ; rr < 16 ; rr++ )
  3313.         {
  3314.           dest[  0 ] = source[  0 ];
  3315.           dest[  1 ] = source[  1 ];
  3316.           dest[  2 ] = source[  2 ];
  3317.           dest[  3 ] = source[  3 ];
  3318.           dest[  4 ] = source[  4 ];
  3319.           dest[  5 ] = source[  5 ];
  3320.           dest[  6 ] = source[  6 ];
  3321.           dest[  7 ] = source[  7 ];
  3322.           dest[  8 ] = source[  8 ];
  3323.           dest[  9 ] = source[  9 ];
  3324.           dest[ 10 ] = source[ 10 ];
  3325.           dest[ 11 ] = source[ 11 ];
  3326.           dest[ 12 ] = source[ 12 ];
  3327.           dest[ 13 ] = source[ 13 ];
  3328.           dest[ 14 ] = source[ 14 ];
  3329.           dest[ 15 ] = source[ 15 ];
  3330.  
  3331.           dest   += 16;
  3332.           source += row_size;
  3333.         }
  3334.       }
  3335.       else
  3336.       {
  3337.         if( right & 0x2 )
  3338.         {
  3339.           /* Half-word bit aligned, use 16 bit copy */
  3340.           WORD *src = (WORD *)source;
  3341.           WORD *d   = (WORD *)dest;
  3342.           row_size >>= 1;
  3343.  
  3344.           for( rr = 0 ; rr < 16 ; rr++ )
  3345.           {
  3346.             d[ 0 ] = src[ 0 ];
  3347.             d[ 1 ] = src[ 1 ];
  3348.             d[ 2 ] = src[ 2 ];
  3349.             d[ 3 ] = src[ 3 ];
  3350.             d[ 4 ] = src[ 4 ];
  3351.             d[ 5 ] = src[ 5 ];
  3352.             d[ 6 ] = src[ 6 ];
  3353.             d[ 7 ] = src[ 7 ];
  3354.  
  3355.             d   += 8;
  3356.             src += row_size;
  3357.           }
  3358.         }
  3359.         else
  3360.         {
  3361.           /* Word aligned, use 32 bit copy */
  3362.           int *src = (int *)source;
  3363.           int *d   = (int *)dest;
  3364.           row_size >>= 2;
  3365.  
  3366.           for( rr = 0 ; rr < 16 ; rr++ )
  3367.           {
  3368.             d[ 0 ] = src[ 0 ];
  3369.             d[ 1 ] = src[ 1 ];
  3370.             d[ 2 ] = src[ 2 ];
  3371.             d[ 3 ] = src[ 3 ];
  3372.  
  3373.             d   += 4;
  3374.             src += row_size;
  3375.           }
  3376.         }
  3377.       }
  3378.     }
  3379.     else
  3380.     {
  3381.       source2 = source + right_half + (row_size * down_half);
  3382.  
  3383.       for( rr = 0 ; rr < width ; rr++ )
  3384.       {
  3385.         dest[  0 ] = (int)(source[  0 ] + source2[  0 ]) >> 1;
  3386.         dest[  1 ] = (int)(source[  1 ] + source2[  1 ]) >> 1;
  3387.         dest[  2 ] = (int)(source[  2 ] + source2[  2 ]) >> 1;
  3388.         dest[  3 ] = (int)(source[  3 ] + source2[  3 ]) >> 1;
  3389.         dest[  4 ] = (int)(source[  4 ] + source2[  4 ]) >> 1;
  3390.         dest[  5 ] = (int)(source[  5 ] + source2[  5 ]) >> 1;
  3391.         dest[  6 ] = (int)(source[  6 ] + source2[  6 ]) >> 1;
  3392.         dest[  7 ] = (int)(source[  7 ] + source2[  7 ]) >> 1;
  3393.         dest[  8 ] = (int)(source[  8 ] + source2[  8 ]) >> 1;
  3394.         dest[  9 ] = (int)(source[  9 ] + source2[  9 ]) >> 1;
  3395.         dest[ 10 ] = (int)(source[ 10 ] + source2[ 10 ]) >> 1;
  3396.         dest[ 11 ] = (int)(source[ 11 ] + source2[ 11 ]) >> 1;
  3397.         dest[ 12 ] = (int)(source[ 12 ] + source2[ 12 ]) >> 1;
  3398.         dest[ 13 ] = (int)(source[ 13 ] + source2[ 13 ]) >> 1;
  3399.         dest[ 14 ] = (int)(source[ 14 ] + source2[ 14 ]) >> 1;
  3400.         dest[ 15 ] = (int)(source[ 15 ] + source2[ 15 ]) >> 1;
  3401.  
  3402.         dest    += width;
  3403.         source  += row_size;
  3404.         source2 += row_size;
  3405.       }
  3406.     }
  3407.   }
  3408.   else
  3409.   {
  3410.     /* must be (width == 8) */
  3411.     assert( width == 8 );
  3412.  
  3413.     if( (!right_half) && (!down_half) )
  3414.     {
  3415.       if( right & 0x1 )
  3416.       {
  3417.         for( rr = 0 ; rr < width ; rr++ )
  3418.         {
  3419.           dest[ 0 ] = source[ 0 ];
  3420.           dest[ 1 ] = source[ 1 ];
  3421.           dest[ 2 ] = source[ 2 ];
  3422.           dest[ 3 ] = source[ 3 ];
  3423.           dest[ 4 ] = source[ 4 ];
  3424.           dest[ 5 ] = source[ 5 ];
  3425.           dest[ 6 ] = source[ 6 ];
  3426.           dest[ 7 ] = source[ 7 ];
  3427.  
  3428.           dest   += 8;
  3429.           source += row_size;
  3430.         }
  3431.       }
  3432.       else
  3433.       {
  3434.         if( right & 0x02 )
  3435.         {
  3436.           WORD *d   = (WORD *)dest;
  3437.           WORD *src = (WORD *)source;
  3438.           row_size >>= 1;
  3439.  
  3440.           for( rr = 0 ; rr < width ; rr++ )
  3441.           {
  3442.             d[ 0 ] = src[ 0 ];
  3443.             d[ 1 ] = src[ 1 ];
  3444.             d[ 2 ] = src[ 2 ];
  3445.             d[ 3 ] = src[ 3 ];
  3446.  
  3447.             d   += 4;
  3448.             src += row_size;
  3449.           }
  3450.         }
  3451.         else
  3452.         {
  3453.           int *d   = (int *)dest;
  3454.           int *src = (int *)source;
  3455.  
  3456.           row_size >>= 2;
  3457.           for( rr = 0 ; rr < width ; rr++ )
  3458.           {
  3459.             d[ 0 ] = src[ 0 ];
  3460.             d[ 1 ] = src[ 1 ];
  3461.  
  3462.             d   += 2;
  3463.             src += row_size;
  3464.           }
  3465.         }
  3466.       }
  3467.     }
  3468.     else
  3469.     {
  3470.       source2 = source + right_half + (row_size * down_half);
  3471.  
  3472.       for( rr = 0 ; rr < width ; rr++ )
  3473.       {
  3474.         dest[ 0 ] = (int)(source[ 0 ] + source2[ 0 ]) >> 1;
  3475.         dest[ 1 ] = (int)(source[ 1 ] + source2[ 1 ]) >> 1;
  3476.         dest[ 2 ] = (int)(source[ 2 ] + source2[ 2 ]) >> 1;
  3477.         dest[ 3 ] = (int)(source[ 3 ] + source2[ 3 ]) >> 1;
  3478.         dest[ 4 ] = (int)(source[ 4 ] + source2[ 4 ]) >> 1;
  3479.         dest[ 5 ] = (int)(source[ 5 ] + source2[ 5 ]) >> 1;
  3480.         dest[ 6 ] = (int)(source[ 6 ] + source2[ 6 ]) >> 1;
  3481.         dest[ 7 ] = (int)(source[ 7 ] + source2[ 7 ]) >> 1;
  3482.  
  3483.         dest    += width;
  3484.         source  += row_size;
  3485.         source2 += row_size;
  3486.       }
  3487.     }
  3488.   }
  3489. }
  3490.  
  3491.  
  3492. /*
  3493.  *--------------------------------------------------------------
  3494.  *
  3495.  * DoPictureDisplay --
  3496.  *
  3497.  *    Converts image from Lum, Cr, Cb to colormap space. Puts
  3498.  *      image in lum plane. Updates past and future frame
  3499.  *      pointers. Dithers image. Sends to display mechanism.
  3500.  *
  3501.  * Results:
  3502.  *    Pict image structure locked if displaying or if frame
  3503.  *      is needed as past or future reference.
  3504.  *
  3505.  * Side effects:
  3506.  *    Lum plane pummelled.
  3507.  *
  3508.  *--------------------------------------------------------------
  3509.  */
  3510.  
  3511.  
  3512. static
  3513. void DoPictureDisplay( struct MPEGVideoInstData *mvid, VidStream *vid_stream )
  3514. {
  3515.     /* Convert to colormap space and dither. */
  3516.     DoDitherImage( mvid,
  3517.                    (vid_stream -> current -> luminance),
  3518.                    (vid_stream -> current -> Cr),
  3519.                    (vid_stream -> current -> Cb),
  3520.                    (vid_stream -> current -> display),
  3521.                    ((vid_stream -> mb_height) * 16),
  3522.                    ((vid_stream -> mb_width)  * 16) );
  3523.  
  3524.     /* Update past and future references if needed. */
  3525.     if( (vid_stream -> picture . code_type == I_TYPE) || (vid_stream -> picture . code_type == P_TYPE) )
  3526.     {
  3527.       if( vid_stream -> future == NULL )
  3528.       {
  3529.         vid_stream -> future            = vid_stream -> current;
  3530.         vid_stream -> future -> locked |= FUTURE_LOCK;
  3531.       }
  3532.       else
  3533.       {
  3534.         if( vid_stream -> past )
  3535.         {
  3536.           vid_stream -> past -> locked &= ~PAST_LOCK;
  3537.         }
  3538.  
  3539.         vid_stream -> past              = vid_stream -> future;
  3540.         vid_stream -> past -> locked   &= ~FUTURE_LOCK;
  3541.         vid_stream -> past -> locked   |= PAST_LOCK;
  3542.         vid_stream -> future            = vid_stream -> current;
  3543.         vid_stream -> future -> locked |= FUTURE_LOCK;
  3544.         vid_stream -> current           = vid_stream -> past;
  3545.  
  3546.         ExecuteDisplay( mvid, vid_stream );
  3547.       }
  3548.     }
  3549.     else
  3550.     {
  3551.       ExecuteDisplay( mvid, vid_stream );
  3552.     }
  3553. }
  3554.  
  3555.  
  3556. ULONG GetFrameRate( struct MPEGVideoInstData *mvid, VidStream *stream )
  3557. {
  3558.     /* Video rates table (taken from mpeg2enc and mpeg_play 2.3) */
  3559.     /* Cheat on Vid rates, round to 30, and use 30 if illegal value
  3560.      * Except for 9, where Xing means 15, and given their popularity, we'll
  3561.      * be nice and do it
  3562.      */
  3563.     const
  3564.     double ratetab[ 16 ] =
  3565.     {
  3566.       30U,  /* reserved */
  3567.       24000.0/1001.0,
  3568.       24.0,
  3569.       25.0,
  3570.       30000.0/1001.0,
  3571.       30.0,
  3572.       50.0,
  3573.       60000.0/1001.0,
  3574.       60.0,
  3575.       15.0, /* reserved */
  3576.       30.0, /* reserved */
  3577.       30.0, /* reserved */
  3578.       30.0, /* reserved */
  3579.       30.0, /* reserved */
  3580.       30.0, /* reserved */
  3581.       30.0  /* reserved */
  3582.     };
  3583.  
  3584.     UBYTE  ratecode = stream -> picture_rate;
  3585.     double fps;
  3586.     ULONG  ticksperframe;
  3587.  
  3588.     if( ratecode < 16U )
  3589.     {
  3590.       fps = ratetab[ ratecode ];
  3591.     }
  3592.     else
  3593.     {
  3594.       fps = 30.0;
  3595.     }
  3596.  
  3597.     ticksperframe = (ULONG)((double)TICK_FREQ / fps);
  3598.  
  3599.     return( ticksperframe );
  3600. }
  3601.  
  3602.  
  3603.